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

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

動(dòng)畫!
如果你想嘗試這些動(dòng)畫效果,本文所有實(shí)例都能在 Github 上的這款 Android 應(yīng)用 中找到。
筆者非常喜歡動(dòng)畫效果,因?yàn)樗粌H提高用戶參與度,還能迅速奪人眼球。想想那些以動(dòng)畫設(shè)計(jì)著稱的應(yīng)用,它們使用起來是多么可心、流暢、自然。

Falcon Pro:即使細(xì)微的動(dòng)畫效果也可以對用戶體驗(yàn)產(chǎn)生巨大影響。
現(xiàn)在,與那些你很喜歡但沒有動(dòng)畫的應(yīng)用做一番比較。

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)展示波紋效果;

波紋在接觸點(diǎn)開始,之后填充整個(gè)視圖背景。
?android:attr/selectableItemBackgroundBorderless –將波紋效果延伸至視圖之外。

圓形波紋效果在接觸點(diǎn)開始,并沿半徑延伸至視圖之外。
View Property Animator
ViewPropertyAnimator 在 API 12 首次引入,允許我們只使用一個(gè)Animator實(shí)例,就可以簡單高效地使多個(gè)視圖屬性(并行地)執(zhí)行動(dòng)畫操作。

此處將繪制下文提到的所有動(dòng)畫屬性。
- alpha() –設(shè)定動(dòng)畫的 alpha 值;
- scaleX() 與 scaleY() – 將視圖縮放于 X 和/或 Y 坐標(biāo)軸;
- translationZ()-在 Z 軸上平移視圖;
- setDuration() –設(shè)置動(dòng)畫時(shí)長;
- setStartDelay() –設(shè)置動(dòng)畫延時(shí);
- setInterpolator() – 設(shè)置動(dòng)畫插值;
- setListener() – 為動(dòng)畫的開始、結(jié)束、重復(fù)、取消設(shè)置偵聽器。
注意: 如果已在視圖中設(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ì)再開始。

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

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

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á)成下圖的效果:

使用自定義屬性時(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è)備上一探究竟。
- No Interpolator -該視圖動(dòng)畫沒有變化率;
- Fast-Out Linear-In

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

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

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

該視圖在動(dòng)畫開始時(shí)加速,并在接近結(jié)束時(shí)逐漸減速。
- Accelerate –視圖逐漸加速直到動(dòng)畫結(jié)束;
- Decelerate –視圖逐漸減速直到動(dòng)畫結(jié)束;
- Anticipate –在以標(biāo)準(zhǔn)方式開始動(dòng)畫之前,視圖先進(jìn)行輕微反轉(zhuǎn);
- Anticipate-Overshoot –與 Anticipate 類似,但動(dòng)畫過程中,回拉動(dòng)作更為夸張;
- BounceInterpolator – 視圖動(dòng)畫結(jié)束之前會(huì)有‘反彈’效果;
- LinearInterpolator – 視圖以線型平滑的動(dòng)畫開始,直到結(jié)束;
- OvershootInterpolator – 視圖動(dòng)畫先放大給定值,再縮回原值。
Circular Reveal
CircularReveal 使用剪切的圓形顯示或隱藏一組 UI 元素。該動(dòng)畫除了帶來視覺上的連續(xù)性,還十分賞心悅目,有助于提高用戶參與度。

如上圖所示,在視圖的動(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)生爆炸效果。

在網(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è)新切換更加靈活。

滑動(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è)置切換的slideEdge為end(右側(cè)),從而實(shí)現(xiàn)從右側(cè)開始滑動(dòng)——若想要底部滑動(dòng)將設(shè)置為 bottom。
漸變
漸變切換使活動(dòng)轉(zhuǎn)換出現(xiàn)淡入或淡出的效果。

在視圖中使用漸變動(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)畫更為人性化,并給用戶帶來更好的視覺感受。

這里,第一個(gè)頁面中的視圖縮小并平移至第二個(gè)頁面的標(biāo)題圖片位置。
在布局中,必須使用 transitionName 屬性將所有共享視圖聯(lián)系起來——這表明了視圖間的轉(zhuǎn)換關(guān)系。下圖展示了之前動(dòng)畫中的共享視圖:

這些都是共享視圖,意味著它們會(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());

轉(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ì)非常有用。具體如下所示:

該動(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)圖片。

在圖片上做幾種不同的動(dòng)畫并不容易。
那么如何完成呢,請看下圖:

該圖由幾個(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>

該矢量由 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>

該矢量由ic_remove.xml 文件(如下所示)生成
接下來聲明 Animated Vector Drawable 文件,其中包含 Vector Drawable 和每個(gè)圖片狀態(tài)動(dòng)畫(Add 或 Remove)的聲明。檢查從 Add 到 Remove 的矢量動(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)畫(從 Remove 到 Add)所需的操作方法相同,只不過將動(dòng)畫值反置。

完成后的動(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)致卡頓。即:
- 手勢滑動(dòng)速度
- 幀率
- 觸摸事件響應(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ù)博客。