探索安卓中有意義的動(dòng)畫!

ribot 致力于打造美好且充滿意義的用戶體驗(yàn),在這一過程中,動(dòng)畫不可或缺。

google
google

在 Droidcon London 聽完一場 激勵(lì)人心的演講之后, 筆者決定深入研究安卓動(dòng)畫。本文集中展示了其研究結(jié)果,希望使開發(fā)者和設(shè)計(jì)者們意識(shí)到,為 Android 應(yīng)用添加漂亮的動(dòng)畫并不復(fù)雜。

animate
animate

動(dòng)畫!

如果你想嘗試這些動(dòng)畫效果,本文所有實(shí)例都能在 Github 上的這款 Android 應(yīng)用 中找到。

筆者非常喜歡動(dòng)畫效果,因?yàn)樗粌H提高用戶參與度,還能迅速奪人眼球。想想那些以動(dòng)畫設(shè)計(jì)著稱的應(yīng)用,它們使用起來是多么可心、流暢、自然。

falcon pro
falcon pro

Falcon Pro:即使細(xì)微的動(dòng)畫效果也可以對用戶體驗(yàn)產(chǎn)生巨大影響。

現(xiàn)在,與那些你很喜歡但沒有動(dòng)畫的應(yīng)用做一番比較。

medium
medium

Medium: 盡管筆者很喜愛 medium APP,但它的確缺少恰當(dāng)?shù)膭?dòng)畫。

小動(dòng)作也能造就大不同

我們可以從多個(gè)方面利用動(dòng)畫,從而:

  • 通過導(dǎo)航上下文傳輸用戶;
  • 強(qiáng)化元素的層級結(jié)構(gòu);
  • 展示屏幕顯示的組件變化。

本文旨在說明,在應(yīng)用中實(shí)現(xiàn)有意義的動(dòng)畫十分簡單可行——那么,即刻開始吧。

觸覺反饋

在用戶觸摸屏幕時(shí)提供反饋,有助于視覺交流,形成互動(dòng)。這些動(dòng)畫不應(yīng)分散用戶的注意力,但又使他們享受其中,獲得清晰的視感,從而鼓勵(lì)進(jìn)一步操作。

安卓框架為此類反饋提供了波紋效果,通過設(shè)定視圖背景,即可使用:

?android:attr/selectableItemBackground-在視圖范圍內(nèi)展示波紋效果;

ripple
ripple

波紋在接觸點(diǎn)開始,之后填充整個(gè)視圖背景。

?android:attr/selectableItemBackgroundBorderless –將波紋效果延伸至視圖之外。

ripple2
ripple2

圓形波紋效果在接觸點(diǎn)開始,并沿半徑延伸至視圖之外。

View Property Animator

ViewPropertyAnimator 在 API 12 首次引入,允許我們只使用一個(gè)Animator實(shí)例,就可以簡單高效地使多個(gè)視圖屬性(并行地)執(zhí)行動(dòng)畫操作。

viewproperty
viewproperty

此處將繪制下文提到的所有動(dòng)畫屬性。

注意: 如果已在視圖中設(shè)置了偵聽器,并打算在相同視圖下,實(shí)現(xiàn)其他動(dòng)畫且不使用回調(diào)函數(shù),則需要將偵聽器設(shè)為 null

用程序?qū)崿F(xiàn)時(shí),簡單又整潔:

 mButton.animate()
        .alpha(1f)
        .scaleX(1f)
        .scaleY(1f)
        .translationZ(10f)
        .setInterpolator(new FastOutSlowInInterpolator())
        .setStartDelay(200)
        .setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) { }

            @Override
            public void onAnimationEnd(Animator animation) { }

            @Override
            public void onAnimationCancel(Animator animation) { }

            @Override
            public void onAnimationRepeat(Animator animation) { }
        })
        .start();

注意: 其實(shí)我們不需要在動(dòng)畫生成器中調(diào)用 start( ) 方法,因?yàn)樵谕V孤暶鞯耐瑫r(shí),動(dòng)畫就會(huì)自動(dòng)啟動(dòng)。在這種情況下,只有在 UI toolkit 事件隊(duì)列開始下一次更新時(shí),動(dòng)畫才會(huì)再開始。

alpha
alpha

制作 FAB 的 alpha 動(dòng)畫值

x,y
x,y

FAB 的(X 和 Y 軸)坐標(biāo)動(dòng)畫

z
z

FAB 的 Z 坐標(biāo)動(dòng)畫

注意: 考慮到向后兼容性,你可以使用ViewCompat 類,來實(shí)現(xiàn)在安卓 API 4 以及以上版本的ViewPropertyAnimator 類。

Object Animator

ViewPropertyAnimator 類似,ObjectAnimator 允許我們在目標(biāo)視圖(代碼和 XML 源文件中)的不同屬性中執(zhí)行動(dòng)畫。然而,它們還是有些差異的:

  • 在每個(gè)實(shí)例中,ObjectAnimator 只允許對單一屬性執(zhí)行動(dòng)畫。例如,坐標(biāo) Y坐標(biāo) X 變化;
  • 但是,它允許自定義屬性的動(dòng)畫,例如視圖的前景色。

使用自定義屬性給視圖做縮放動(dòng)畫,并改變其前景色,可以達(dá)成下圖的效果:

custom
custom

使用自定義屬性時(shí),可以通過調(diào)用ObjectAnimator.ofInt(),創(chuàng)建一個(gè)ObjectAnimator實(shí)例,此處我們聲明:

  • view – 應(yīng)用動(dòng)畫的視圖;
  • property – 設(shè)定動(dòng)畫的屬性;
  • start color – 動(dòng)畫視圖的初始顏色;
  • target color – 動(dòng)畫視圖的目標(biāo)顏色。

接下來,設(shè)置評估器(此處使用ArgbEvaluator 設(shè)置顏色動(dòng)畫),設(shè)置延遲并執(zhí)行 start( )。

private void animateForegroundColor(@ColorInt final int targetColor) {
    ObjectAnimator animator = 
        ObjectAnimator.ofInt(YOUR_VIEW, FOREGROUND_COLOR, Color.TRANSPARENT, targetColor);
    animator.setEvaluator(new ArgbEvaluator());
    animator.setStartDelay(DELAY_COLOR_CHANGE);
    animator.start();
}

接下來,使用相似的方法做視圖縮放的動(dòng)畫,主要區(qū)別在于:

  • 使用ObjectAnimator.ofFloat() 創(chuàng)建 ObjectAnimator 實(shí)例,因?yàn)樵谡{(diào)整視圖大小時(shí),并沒有改動(dòng)整型值;
  • 使用 View.SCALE_X 和 View.SCALE_Y 視圖屬性,而非自定義屬性。
    private void resizeView() {
        final float widthHeightRatio = (float)     getHeight() / (float) getWidth();
        resizeViewProperty(View.SCALE_X, .5f, 200);
        resizeViewProperty(View.SCALE_Y, .5f / widthHeightRatio, 250);
    }
    
    private void resizeViewProperty(Property<View, Float> property,
                                    float targetScale, 
                                    int durationOffset) {
        ObjectAnimator animator = ObjectAnimator.ofFloat(this, property, 1f, targetScale);
        animator.setInterpolator(new LinearOutSlowInInterpolator());
        animator.setStartDelay(DELAY_COLOR_CHANGE + durationOffset);
        animator.start();
    }

最后,將調(diào)整完大小的視圖移開屏幕。在這種情況下,使用AdapterViewFlipper 容納離屏視圖,可以對 ViewFlipper 實(shí)例調(diào)用showNext()方法,后者會(huì)使用(定義好的動(dòng)畫處理該過程。接著,下一個(gè)視圖也會(huì)使用定義好的入場動(dòng)畫,自動(dòng)出現(xiàn)在屏幕上。

Interpolators

Interpolator 可用于定義動(dòng)畫的變化率,意味著動(dòng)畫的速度、加速度、行為都可以改變。可用的 interpolator 有數(shù)種,且相互之間的差別微乎其微,建議讀者在設(shè)備上一探究竟。

fast1
fast1

該視圖以線型動(dòng)作開始和結(jié)束動(dòng)畫。

fast2
fast2

該視圖開始動(dòng)作很快,逐漸降速直至結(jié)束。

linear
linear

該視圖以線型動(dòng)作開始,逐漸降速直至結(jié)束。

accelarate
accelarate

該視圖在動(dòng)畫開始時(shí)加速,并在接近結(jié)束時(shí)逐漸減速。

Circular Reveal

CircularReveal 使用剪切的圓形顯示或隱藏一組 UI 元素。該動(dòng)畫除了帶來視覺上的連續(xù)性,還十分賞心悅目,有助于提高用戶參與度。

circular
circular

如上圖所示,在視圖的動(dòng)畫效果顯示之前,使用 ViewPropertyAnimator 隱藏浮動(dòng)操作圖標(biāo)。只需定義如下屬性就可以配置 circular reveal:

  • startView – CircularReveal 的開始視圖(即壓縮視圖);
  • centerX –點(diǎn)擊視圖的 X軸中心;
  • centerY -點(diǎn)擊視圖的 Y軸中心;
  • targetView –要顯示的視圖;
  • finalRadius –剪切圓的半徑,大小等于以 X 中心和 Y 中心為直角邊的三角形的斜邊的值。
int centerX = (startView.getLeft() + startView.getRight()) / 2;
int centerY = (startView.getTop() + startView.getBottom()) / 2;
float finalRadius = (float) Math.hypot((double) centerX, (double) centerY);
Animator mCircularReveal = ViewAnimationUtils.createCircularReveal(
  targetView, centerX, centerY, 0, finalRadius);

窗口轉(zhuǎn)換

定制用于活動(dòng)間導(dǎo)航的轉(zhuǎn)換,可使用戶對應(yīng)用狀態(tài)產(chǎn)生更為強(qiáng)烈的視覺聯(lián)系。默認(rèn)情況可定制如下轉(zhuǎn)換:

  • enter –決定活動(dòng)視圖如何進(jìn)入場景;
  • exit -決定活動(dòng)視圖如何退出場景;
  • reenter –決定活動(dòng)視圖退出后如何再度進(jìn)入;
  • shared elements –決定活動(dòng)間如何共享視圖轉(zhuǎn)換。

API 21起,還有如下幾種新的轉(zhuǎn)換方式:

爆炸

Explode 轉(zhuǎn)換允許視圖從屏幕各個(gè)方位退出,會(huì)使壓縮視圖產(chǎn)生爆炸效果。

explode
explode

在網(wǎng)格布局中爆炸效果尤其好。

這種效果易于實(shí)現(xiàn)——首先,需要在 res/transition 目錄中創(chuàng)建如下轉(zhuǎn)換:

<explode xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"/>

具體做法如下:

  • 聲明 explode 轉(zhuǎn)換;
  • 設(shè)置持續(xù)時(shí)間為300毫秒。

接下來,需要將此設(shè)置為活動(dòng)的轉(zhuǎn)換。既可以將其添加到活動(dòng)主題:

<style name="AppTheme.Explode" parent="AppTheme.NoActionBar">
  <item name="android:windowExitTransition">@transition/slide_explode</item>
  <item name="android:windowReenterTransition">@android:transition/slide_top</item>
</style>

也可以編程的方式解決:

Transition explode = TransitionInflater.from(this).inflateTransition(R.transition.explode);
getWindow().setEnterTransition(explode);

滑動(dòng)

滑動(dòng)切換可以使活動(dòng)從屏幕右側(cè)或底部滑入/出。可能你以前有過類似的效果,但是這個(gè)新切換更加靈活。

slide
slide

滑動(dòng)切換使我們依次滑動(dòng)子視圖

這種轉(zhuǎn)換在切換活動(dòng)時(shí)尤為常見,筆者對向右側(cè)滑的流暢感覺情有獨(dú)鐘,當(dāng)然這也很容易創(chuàng)建:

<slide xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/decelerate_cubic"
    android:slideEdge="end"/>

在這里:

  • 聲明了 slide 轉(zhuǎn)換;
  • 設(shè)置切換的slideEdgeend(右側(cè)),從而實(shí)現(xiàn)從右側(cè)開始滑動(dòng)——若想要底部滑動(dòng)將設(shè)置為 bottom。

漸變

漸變切換使活動(dòng)轉(zhuǎn)換出現(xiàn)淡入或淡出的效果。

fade
fade

在視圖中使用漸變動(dòng)畫操作簡單,且效果宜人。

創(chuàng)建此切換的操作比之前的切換更加簡單:

<fade xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="300"/>

在這里:

  • 聲明了 fade 轉(zhuǎn)換;
  • 設(shè)置持續(xù)時(shí)間為300毫秒。

優(yōu)化轉(zhuǎn)換

實(shí)驗(yàn)的同時(shí),筆者發(fā)現(xiàn)了一些可以改善上述轉(zhuǎn)換效果的方法。

允許窗口頁面轉(zhuǎn)換——需要在主題中啟用下列屬性,主題都來源于一個(gè)資料主題:

<item name="android:windowContentTransitions">true</item>

啟用/禁用轉(zhuǎn)換重疊——上一轉(zhuǎn)換過程結(jié)束,新的頁面動(dòng)畫才會(huì)開始,這樣就會(huì)形成時(shí)延。在不同的案例中,若啟用如下屬性,轉(zhuǎn)換過程都會(huì)更加流暢自然:

<item name="android:windowAllowEnterTransitionOverlap">true</item>
<item name="android:windowAllowReturnTransitionOverlap">true</item>

排除特定視圖轉(zhuǎn)換—有時(shí)我們并不想讓活動(dòng)中的所有視圖參與動(dòng)畫,而且大多數(shù)情況下,工具欄和狀態(tài)欄是造成轉(zhuǎn)換故障主因。所幸,可以排除特定的視圖,使之無法轉(zhuǎn)換:

     <explode xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="200">
        <targets>
            <target android:excludeId="@android:id/navigationBarBackground"/>
            <target android:excludeId="@android:id/statusBarBackground"/>
        </targets>
      </explode>

工具欄和操作欄——當(dāng)使用操作欄的活動(dòng)向使用工具欄的活動(dòng)轉(zhuǎn)換時(shí)(反之亦然),轉(zhuǎn)換過程總是磕磕絆絆。為此,應(yīng)當(dāng)確保轉(zhuǎn)換中的兩個(gè)活動(dòng)都使用相同的組件。

轉(zhuǎn)換持續(xù)時(shí)間——既不能讓用戶等太久,也不能讓動(dòng)畫轉(zhuǎn)換過快。這取決于轉(zhuǎn)換持續(xù)時(shí)間,最好通過試驗(yàn)敲定恰當(dāng)?shù)臅r(shí)間。筆者發(fā)現(xiàn),多數(shù)情況下200-500微秒最為合適。

共享元素轉(zhuǎn)換

共享元素轉(zhuǎn)換方便我們?yōu)轫撁骈g的共享視圖制作動(dòng)畫,使動(dòng)畫更為人性化,并給用戶帶來更好的視覺感受。

shared
shared

這里,第一個(gè)頁面中的視圖縮小并平移至第二個(gè)頁面的標(biāo)題圖片位置。

在布局中,必須使用 transitionName 屬性將所有共享視圖聯(lián)系起來——這表明了視圖間的轉(zhuǎn)換關(guān)系。下圖展示了之前動(dòng)畫中的共享視圖:

link
link

這些都是共享視圖,意味著它們會(huì)在每次頁面轉(zhuǎn)換過程中形成動(dòng)畫。

為了完成如上轉(zhuǎn)換,我們首先要聲明共享轉(zhuǎn)換名稱,可以通過使用 XML 布局中的 transitionName 屬性來完成。

屏幕 1)

<RelativeLayout>
    <LinearLayout>

        <View 
            android:id="@+id/view_shared_transition"
            android:transitionName="@string/transition_view"/>

        <!-- Your other views -->

    </LinearLayout>
</RelativeLayout>

屏幕2)

<LinearLayout>

    <View
        android:id="@+id/view_shared_transition"
        android:transitionName="@string/transition_view"/>

    <View
        android:id="@+id/view_separator"/>

    <TextView
        android:id="@+id/text_detail"/>

    <TextView
        android:id="@+id/text_close"/>

</LinearLayout>

之后,在頁面1中創(chuàng)建 Pair 對象,使之包含轉(zhuǎn)換視圖與其 transitionName。然后將其傳給頁面選擇實(shí)例(ActivityOptionsCompat),由此兩個(gè)頁面都得知了共享組件,就可以開始動(dòng)畫了。

Pair participants = new Pair<>(mSquareView, ViewCompat.getTransitionName(mSquareView));

ActivityOptionsCompat transitionActivityOptions = 
        ActivityOptionsCompat.makeSceneTransitionAnimation(
                SharedTransitionsActivity.this, participants);

ActivityCompat.startActivity(SharedTransitionsActivity.this, 
                      intent, transitionActivityOptions.toBundle());
sliding
sliding

轉(zhuǎn)換的同時(shí)滑動(dòng)這些視圖,有助于完成轉(zhuǎn)換。

以上就是兩個(gè)視圖間的轉(zhuǎn)換,那么在第二個(gè)頁面中從底部滑入的視圖怎么辦呢?

(它們就是左邊的那些視圖)

其實(shí)這個(gè)實(shí)現(xiàn)過程也很簡單,如下:

Slide slide = new Slide(Gravity.BOTTOM);
slide.addTarget(R.id.view_separator);
slide.addTarget(R.id.text_detail);
slide.addTarget(R.id.text_close);
getWindow().setEnterTransition(slide);

如你所見,創(chuàng)建一個(gè)新的Slide 轉(zhuǎn)換:將目標(biāo)視圖添加到轉(zhuǎn)換中,并將滑動(dòng)動(dòng)作設(shè)為入場動(dòng)畫。

自定義轉(zhuǎn)換

我們也可以使用之前介紹過的 API 動(dòng)畫創(chuàng)建自己的自定義轉(zhuǎn)換。例如,將共享元素轉(zhuǎn)換衍伸,成為轉(zhuǎn)換視圖變體——當(dāng)我們需要顯示對話框(或者類似的彈框視圖)時(shí),自定義轉(zhuǎn)換就會(huì)非常有用。具體如下所示:

custom2
custom2

該動(dòng)畫可以在組件狀態(tài)間引導(dǎo)用戶的注意力。

先來簡單了解一下上圖發(fā)生了什么:

  • 首先創(chuàng)建一個(gè)SharedTransition,傳入壓縮視圖與轉(zhuǎn)換名稱以引用共享組件。
  • 然后創(chuàng)建ArcMotion 實(shí)例,使兩個(gè)視圖轉(zhuǎn)換時(shí)形成曲線動(dòng)畫效果。
  • 接下來擴(kuò)展 ChangeBounds 以創(chuàng)建自定義轉(zhuǎn)換,改變(morph)兩個(gè)形狀(對于button 和 FAB ,有兩個(gè)不同的類)。此處重寫了類中的多個(gè)方法,以便為所需屬性做動(dòng)畫。最后,使用 ViewPropertyAnimator 調(diào)整對話框的透明度,使用 ObjectAnimator 調(diào)整兩個(gè)視圖間的色彩,使用 AnimatorSet 實(shí)例將兩種動(dòng)畫效果整合在一起。

動(dòng)態(tài)矢量圖片

API 21中(Lollipop),AnimatedVectorDrawable 可用于制定VectorDrawable 屬性的動(dòng)畫,生成動(dòng)態(tài)圖片。

vectors
vectors

在圖片上做幾種不同的動(dòng)畫并不容易。

那么如何完成呢,請看下圖:

vector2
vector2

該圖由幾個(gè)不同文件組成,首先創(chuàng)建兩個(gè)獨(dú)立的矢量文件,每個(gè)都包含如下屬性:

  • Height & Width –矢量圖像的實(shí)際大小;
  • Viewport Height & Width –聲明描述矢量路徑的虛擬畫布的大小;
  • Group name –聲明路徑所屬的組名;
  • Pivot X & Y –聲明群組規(guī)模和旋轉(zhuǎn)所使用的中心點(diǎn);
  • Path Fill Color –描述矢量路徑的填充色;
  • Path Data –聲明用于繪制矢量的矢量路徑數(shù)據(jù)。

注意: 所有被引用的屬性都存儲(chǔ)在 general strings file 中,這樣可以保持程序整潔美觀。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="56dp" 
        android:width="56dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
    <group
        android:name="@string/groupAddRemove"
        android:pivotX="12"
        android:pivotY="12">
        <path 
            android:fillColor="@color/stroke_color"
            android:pathData="@string/path_add"/>
    </group>
</vector>
vector3
vector3

該矢量由 ic_add.xml 文件(如下所示)生成

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="56dp"
        android:width="56dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
    <group
        android:name="@string/groupAddRemove"
        android:pivotX="12"
        android:pivotY="12">
        <path 
            android:fillColor="@color/stroke_color" 
            android:pathData="@string/path_remove"/>
    </group>
</vector>
vectors
vectors

該矢量由ic_remove.xml 文件(如下所示)生成

接下來聲明 Animated Vector Drawable 文件,其中包含 Vector Drawable 和每個(gè)圖片狀態(tài)動(dòng)畫(AddRemove)的聲明。檢查從 AddRemove 的矢量動(dòng)畫,聲明一個(gè)目標(biāo)文件(target)以完成:

  • 狀態(tài)轉(zhuǎn)換的動(dòng)畫;
  • 圖片旋轉(zhuǎn)的動(dòng)畫。
    <animated-vector android:drawable="@drawable/ic_add">
        <target
            android:name="@string/add"
            android:animation="@animator/add_to_remove" />
        <target
            android:name="@string/groupAddRemove"
            android:animation="@animator/rotate_add_to_remove" />
    </animated-vector>

然后創(chuàng)建目標(biāo)文件中引用的每個(gè)文件。

改變圖片狀態(tài)

add_to_remove.xml 文件中,使用ObjectAnimator 改變圖形形狀,其中會(huì)用到如下屬性:

  • propertyName –執(zhí)行動(dòng)畫的屬性;
  • valueFrom –矢量路徑的初始值;
  • valueTo –矢量路徑的目標(biāo)值;
  • duration –動(dòng)畫持續(xù)時(shí)間;
  • interpolator –動(dòng)畫插值器;
  • valueType –動(dòng)畫值類型。
      <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:propertyName="pathData"
        android:valueFrom="@string/path_add"
        android:valueTo="@string/path_remove"
        android:duration="@integer/duration"
        android:interpolator="@android:interpolator/fast_out_slow_in"
        android:valueType="pathType" />

形狀旋轉(zhuǎn)

可使用相似的方法旋轉(zhuǎn)圖像,只是會(huì)用到旋轉(zhuǎn)屬性和旋轉(zhuǎn)值:

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="rotation"
    android:valueFrom="-180"
    android:valueTo="0"
    android:duration="@integer/duration"
    android:interpolator="@android:interpolator/fast_out_slow_in" />

執(zhí)行相反的動(dòng)畫(從 RemoveAdd)所需的操作方法相同,只不過將動(dòng)畫值反置。

rotating
rotating

完成后的動(dòng)態(tài)矢量圖,效果很不錯(cuò)吧?

使用OneAPM分析UI卡頓

使用 OneAPM 可以快速定位分析UI性能,Mobile Insight的卡頓可以直觀地展示這些信息。
[站外圖片上傳中……(29)]
可以分析繪制APP卡頓趨勢圖,精確定位每1秒內(nèi)的繪圖刷新信號中斷的次數(shù),從多維度分析卡頓現(xiàn)象,如APP版本、操作系統(tǒng)版本的分布情況等。
[站外圖片上傳中……(30)]
卡頓詳情列表展示:訪問時(shí)間,發(fā)生卡頓時(shí)的流暢度,耗時(shí),發(fā)生卡頓時(shí)的設(shè)備信息,APP版本,操作系統(tǒng)及版本,CPU信息
通過分析該頁面信息可以清楚了解到卡頓來源,以便針對性快速優(yōu)化。
[站外圖片上傳中……(31)]

動(dòng)畫卡頓原因

動(dòng)畫卡頓的原因大概有這樣三種,這些因素將直接影響動(dòng)畫的性能,導(dǎo)致卡頓。即:

  1. 手勢滑動(dòng)速度
  2. 幀率
  3. 觸摸事件響應(yīng)的速度

手勢滑動(dòng)、幀率是跟各種手機(jī)設(shè)備有直接的關(guān)系,各種各樣的硬件設(shè)備會(huì)表現(xiàn)出不一樣的性能,如果從這個(gè)方面入手考慮優(yōu)化,就十分需要 OneAPM Mobile Insight 這樣的從多維度來分析性能的一款工具。

結(jié)語

雖然只是淺談,文本旨在圍繞創(chuàng)建有意義的動(dòng)畫提供有益的視角,使讀者受益。今后,筆者會(huì)繼續(xù)努力,以求進(jìn)一步改善應(yīng)用的外觀與用戶體驗(yàn)。

原文地址:https://medium.com/ribot-labs/exploring-meaningful-motion-on-android-1cd95a4bc61d#.vqazussmj

OneAPM Mobile Insight 以真實(shí)用戶體驗(yàn)為度量標(biāo)準(zhǔn)進(jìn)行 Crash 分析,監(jiān)控網(wǎng)絡(luò)請求及網(wǎng)絡(luò)錯(cuò)誤,提升用戶留存。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗(yàn),想閱讀更多技術(shù)文章,請?jiān)L問 OneAPM 官方技術(shù)博客。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容