Android讀書筆記(7)—— Android動(dòng)畫深入分析

一、View動(dòng)畫

Android動(dòng)畫分為三種:View動(dòng)畫玻侥、幀動(dòng)畫和屬性動(dòng)畫决摧。

1、View動(dòng)畫的種類

View動(dòng)畫的作用對象是View,支持四種動(dòng)畫效果:平移掌桩、縮放边锁、旋轉(zhuǎn)和透明。上述四種變換效果對應(yīng)著Animation四個(gè)子類: TranslateAnimation 拘鞋、 ScaleAnimation 砚蓬、 RotateAnimationAlphaAnimation。這四種動(dòng)畫皆可以通過XML定義盆色,也可以通過代碼來動(dòng)態(tài)創(chuàng)建灰蛙。建議采用
xml定義動(dòng)畫,具有更好的可讀性隔躲。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
//動(dòng)畫插值器摩梧,影響動(dòng)畫的播放速度
android:interpolator="@android:anim/accelerate_interpolator"
//表示集合中的動(dòng)畫是否和集合共享一個(gè)插值器
android:shareInterpolator="true" 
//表示動(dòng)畫結(jié)束以后,View停留在結(jié)束動(dòng)畫的位置宣旱,如果為false仅父,View會(huì)回到動(dòng)畫開始的位置
android:fillAfter="true" >
//透明度動(dòng)畫,對應(yīng) AlphaAnimation 類浑吟,可以改變 View 的透明度
    <alpha
        android:duration="3000"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
    //旋轉(zhuǎn)動(dòng)畫笙纤,對應(yīng)著 RotateAnimation ,它可以使 View 具有旋轉(zhuǎn)的動(dòng)畫效果
    <rotate
        android:duration="2000"
        android:fromDegrees="0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:startOffset="3000"
        android:toDegrees="180" />
    <!--通過設(shè)置第一個(gè)alpha動(dòng)畫播放3s后啟動(dòng)rotate動(dòng)畫實(shí)現(xiàn)組合動(dòng)畫,如果不設(shè)置startOffset則同時(shí)播放组力。
    pivotX:表示旋轉(zhuǎn)時(shí)候的相對軸的坐標(biāo)點(diǎn)省容,即圍繞哪一點(diǎn)進(jìn)行旋轉(zhuǎn),默認(rèn)情況下軸點(diǎn)是 View 中心
    -->
    //平移動(dòng)畫燎字,對應(yīng) TranslateAnimation 類腥椒,可以使 View 完成垂直或者水平方向的移動(dòng)效果。
    <translate
        android:fromXDelta="500"
        android:toXDelta="0" />
    //縮放動(dòng)畫候衍,對應(yīng) ScaleAnimation 類笼蛛,可以使 View 具有放大和縮小的動(dòng)畫效果。
    <scale
        android:duration="1000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50"
        android:pivotY="50"
        android:toXScale="2"
        android:toYScale="2" />
    </set>

標(biāo)簽表示動(dòng)畫集合蛉鹿,對應(yīng)AnimationSet類滨砍,可以包含一個(gè)或若干個(gè)動(dòng)畫,內(nèi)部還可以嵌套其他動(dòng)畫集合妖异。
android:fillAfter屬性表示動(dòng)畫結(jié)束以后惨好,View是否停留在結(jié)束動(dòng)畫的位置,如果為 false 随闺, View 會(huì)回到動(dòng)畫開始的位置。這個(gè)參數(shù)在動(dòng)畫 XML 文件的 </set> 節(jié)點(diǎn)中設(shè)置或在程序 Java 代碼中進(jìn)行設(shè)置:setFillAfter(true)蔓腐。

定義完View動(dòng)畫的xml后矩乐,通過以下代碼應(yīng)用動(dòng)畫:

Aniamation anim = AnimationUtils.loadAnimation(context,R.anim.animation_test);
view.startAnimation(anim);

代碼動(dòng)態(tài)創(chuàng)建動(dòng)畫

AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
alphaAnimation.setDuration(1500);
view.startAnimation(alphaAnimation);

通過setAnimationListener給View動(dòng)畫添加過程監(jiān)聽

public static interface AnimationListener {
    void onAnimationStart(Animation animation);
    void onAnimationEnd(Animation animation);
    void onAnimationRepeat(Animation animation);
}

2、自定義View動(dòng)畫

除了系統(tǒng)提供的四種動(dòng)畫外,我們可以根據(jù)需求自定義動(dòng)畫散罕,自定義一個(gè)新的動(dòng)畫只需要繼 Animation 這個(gè)抽象類分歇,然后重寫它的inatializeapplyTransformation這兩個(gè)方法,在initialize 方法中做一些初始化工作欧漱,在applyTransformation方法中進(jìn)行矩陣變換即可职抡,很多時(shí)候采用Camera 來簡化矩陣的變換過程。其實(shí)自定義動(dòng)畫的主要過程就是矩陣變換的過程误甚,矩陣變換是數(shù)學(xué)上的概念缚甩,需要掌握該方面知識(shí)方能輕松實(shí)現(xiàn)自定義動(dòng)畫。

3窑邦、幀動(dòng)畫

幀動(dòng)畫是順序播放一組預(yù)先定義好的圖片擅威,使用簡單,但容易引起OOM冈钦,所以在使用幀動(dòng)畫時(shí)應(yīng)盡量避免使用過多尺寸較大的圖片郊丛。系統(tǒng)提供了另一個(gè)類AnimationDrawble來使用幀動(dòng)畫,使用的時(shí)候瞧筛,需要通過XML定義一個(gè)AnimationDrawble厉熟,如下:

//\res\drawable\frame_animation_list.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">//oneshot 代表著是否只展示一遍
    <item
        android:drawable="@drawable/one"
        android:duration="2000"/>
    <item
        android:drawable="@drawable/two"
        android:duration="2000"/>
    <item
        android:drawable="@drawable/three"
        android:duration="2000"/>
</animation-list>

然后將上述Drawable作為View的背景并播放即可

view.setBackgroundResource(R.drawable.frame_animation_list);
AnimationDrawble drawable = (AnimationDrawble)view.getBackground();
drawable.start();

二、View動(dòng)畫的特殊使用場景

View動(dòng)畫除了可以實(shí)現(xiàn)的四種基本的動(dòng)畫效果外较幌,還可以在一些特殊的場景下使用揍瑟,比如在 ViewGroup 中可以控制子元素的出場效果,在Activity中可以實(shí)現(xiàn)不同Activity之間的切換效果绅络。

1月培、LayoutAnimation

作用于ViewGroup,為ViewGroup指定一個(gè)動(dòng)畫恩急,當(dāng)它的子元素出場時(shí)都會(huì)具有這種動(dòng)畫效
果杉畜,一般用在ListView上。

1.1衷恭、一般步驟
  1. 定義一個(gè)LayoutAnimation
//res/anim/layout_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay="0.5"
    android:animationOrder="normal"
    android:animation="@anim/zoom_in">
</layoutAnimation>

android:delay
表示子元素開始動(dòng)畫的延時(shí)時(shí)間此叠,取值為子元素入場動(dòng)畫時(shí)間duration的倍數(shù),比如子元素入場動(dòng)畫時(shí)間周期為 300ms 随珠,那么 0.5 表示每個(gè)子元素都需要延遲 150ms 才能播放入場動(dòng)畫灭袁,即第一個(gè)子元素延遲 150ms 開始播放入場動(dòng)畫,第二個(gè)子元素延遲 300ms 開始播放入場動(dòng)畫窗看,依次類推進(jìn)行茸歧。
android:animationOrder
表示子元素動(dòng)畫的開場順序,normal(正序)显沈、reverse(倒序)软瞎、random(隨機(jī))逢唤。
android:animation
為子元素指定具體的入場動(dòng)畫

  1. 為 ViewGroup 指定屬性
    android:layoutAnimation="@anim/layout_animation"

除了xml中指定LayoutAnimation外,也可以通過LayoutAnimationController來實(shí)現(xiàn)

1.2涤浇、LayoutAnimationController是實(shí)現(xiàn)
//用于控制子 view 動(dòng)畫效果
LayoutAnimationController layoutAnimationController= new LayoutAnimationController(AnimationUtils
.loadAnimation(this,R.anim.zoom_in));
layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(layoutAnimationController);
listView.startLayoutAnimation();

2鳖藕、Activity的切換效果

自定義Activity的切換效果,主要通過overridePendingTransition(int enterAnim, int exitAnim) 方法只锭,enterAnim表示Activity被打開時(shí)候所需的動(dòng)畫資源ID著恩,exitAnim是Activity被暫停時(shí)所需的動(dòng)畫資源ID民逼。該方法必須要在startActivity(intent)和finish()方法之后調(diào)用才會(huì)有效呼巴。

//啟動(dòng)新的Activity帶動(dòng)畫
Intent intent=new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
overridePendingTransition(R.anim.zoom_in,R.anim.zoom_out);
//退出Activity本身帶動(dòng)畫
@Override
public void finish() {
    super.finish();
    overridePendingTransition(R.anim.zoom_in,R.anim.zoom_out);
}

Fragment也可以添加切換動(dòng)畫,通過 FragmentTransation 中的setCustomAnimations() 方法來實(shí)現(xiàn)切換動(dòng)畫羔挡,這個(gè)動(dòng)畫需要的是 View 動(dòng)畫铺呵,不能使用屬性動(dòng)畫裹驰,因?yàn)閷傩詣?dòng)畫也是 API11 才引入的,不兼容片挂。

三幻林、屬性動(dòng)畫

屬性動(dòng)畫是 API 11 引入的新特性,屬性動(dòng)畫可以對任何對象做動(dòng)畫音念,甚至還可以沒有對象沪饺。可以在一個(gè)時(shí)間間隔內(nèi)完成對象從一個(gè)屬性值到另一個(gè)屬性值的改變闷愤。與View動(dòng)畫相比整葡,屬性動(dòng)畫幾乎無所不能,只要對象有這個(gè)屬性讥脐,它都能實(shí)現(xiàn)動(dòng)畫效果遭居。API11以下可以通過nineoldandroids庫來兼容以前版本。

1旬渠、使用屬性動(dòng)畫

屬性動(dòng)畫有ValueAnimator俱萍、ObjectAnimatorAnimatorSet等概念。其中ObjectAnimator繼承自ValueAnimator告丢,AnimatorSet是動(dòng)畫集合枪蘑。

改變一個(gè)對象 TranslationY 屬性,讓其沿著 Y 軸平移一段距離

private void translateViewByObjectAnimator(View targetView){
//TranslationY 目標(biāo) View 要改變的屬性
//ivShow.getHeight() 要移動(dòng)的距離
    ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(targetView,"TranslationY",ivShow.getHeight());
    objectAnimator.start();
}

改變一個(gè)對象的背景色屬性岖免,3秒內(nèi)從0xFFFF8080到0xFF8080FF漸變岳颇,無限循環(huán)且有反轉(zhuǎn)效果

 private void changeViewBackGroundColor(View targetView){
     ValueAnimator valueAnimator=ObjectAnimator.ofInt(targetView,"backgroundColor", Color.RED,Color.BLUE);
     valueAnimator.setDuration(3000);
     //設(shè)置估值器,該處插入顏色估值器
     valueAnimator.setEvaluator(new ArgbEvaluator());
     //無限循環(huán)
     valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
     //反轉(zhuǎn)模式
     valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
     valueAnimator.start();
 }

動(dòng)畫集合颅湘,5 秒內(nèi)對 View 旋轉(zhuǎn)话侧、平移、縮放和透明度進(jìn)行了改變

 private void startAnimationSet(View targetView){
     AnimatorSet animatorSet=new AnimatorSet();
     animatorSet.playTogether(ObjectAnimator.ofFloat(targetView,"rotationX",0,360),
              //旋轉(zhuǎn)
             ObjectAnimator.ofFloat(targetView,"rotationY",0,360),
             ObjectAnimator.ofFloat(targetView,"rotation",0,-90),
              //平移
             ObjectAnimator.ofFloat(targetView,"translationX",0,90),
             ObjectAnimator.ofFloat(targetView,"translationY",0,90),
              //縮放
             ObjectAnimator.ofFloat(targetView,"scaleX",1,1.5f),
             ObjectAnimator.ofFloat(targetView,"scaleY",1,1.5f),
              //透明度
             ObjectAnimator.ofFloat(targetView,"alpha",1,0.25f,1));
             animatorSet.setDuration(3000).start();
 }

也可以通過在xml中定義在 res/animator/ 目錄下闯参。具體如下:

 \res\animator\value_animator.xml
 <?xml version="1.0" encoding="utf-8"?><!--set 標(biāo)簽對應(yīng)著 AnimatorSet-->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
     android:ordering="together">
     <!--對應(yīng)著 ObjectAnimator-->
     <objectAnimator
         android:propertyName="x"
         android:repeatCount="infinite"
         android:repeatMode="reverse"
         android:startOffset="10"
         android:valueTo="300"
         android:valueType="floatType" />
     <!--其中propertyName 屬性設(shè)置為translationX 瞻鹏,valueType 設(shè)置為floatType 可以正常啟動(dòng)
        如果 valueType 設(shè)置為 intType 將報(bào)錯(cuò),即屬性類型必須為 floatType 類型术羔,并且android:propertyName="translationX" 表示移動(dòng) 300 ,而  android:propertyName="x"表示移動(dòng)到300 乙漓,是兩個(gè)不同屬性-->
     <!--startOffset 指定延遲多久開始播放動(dòng)畫-->
     <!--valueType 表示指定的 android:propertyName 所指定屬性的類型,intType 表示指定屬性是整型的释移,
      如果指定屬性為顏色叭披,那么不需要指定 valueType 屬性,系統(tǒng)會(huì)自動(dòng)處理
      repeatCount 表示動(dòng)畫循環(huán)次數(shù)玩讳,默認(rèn)值為0涩蜘,-1 表示無限循環(huán)-->

     <!--對應(yīng)著 ValueAnimator-->
    <animator
     android:duration="300"
     android:valueFrom="0"
     android:valueTo="360"
     android:startOffset="10"
     android:repeatCount="infinite"
     android:repeatMode="reverse"
     android:valueType="intType"/>
 </set>

使用動(dòng)畫

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(context , R.animator.anim);
set.setTarget(view);
set.start();

實(shí)際開發(fā)中建議使用代碼實(shí)現(xiàn)屬性動(dòng)畫。很多時(shí)候一個(gè)屬性的起始值是無法提前確定的熏纯。

2同诫、理解插值器和估值器

時(shí)間插值器( TimeInterpolator)
根據(jù)時(shí)間流逝的百分比來計(jì)算出當(dāng)前屬性值改變的百分比,系統(tǒng)預(yù)置的有LinearInterpolator( 線性插值器:勻速動(dòng)畫) 樟澜,AccelerateDecelerateInterpolator( 加速減速插值器:動(dòng)畫兩頭慢中間快) 误窖,DecelerateInterpolator(減速插值器:動(dòng)畫越來越慢)。

估值器(類型估值算法秩贰, TypeEvaluator)
根據(jù)當(dāng)前屬性改變的百分比來計(jì)算改變后的屬性值霹俺。系統(tǒng)預(yù)置有IntEvaluator(針對整型屬性) 、FloatEvaluator(浮點(diǎn)型屬性) 毒费、ArgbEvaluator(針對 Color 屬性)丙唧。

如圖所示,表示一個(gè)勻速動(dòng)畫觅玻,采用了線性插值器和整型估值算法想际,在 40ms 內(nèi),View 的 X 屬性實(shí)現(xiàn)了從 0 到 40 的變化溪厘。

屬性動(dòng)畫要求對象的該屬性有 set 和 get(可選) 方法胡本,插值器和估值算法除了系統(tǒng)提供的外,我們還可以自己定義桩匪,插值器或者估值算法都是一個(gè)接口打瘪,且內(nèi)部只有一個(gè)方法,我們只需要派生一個(gè)類實(shí)現(xiàn)該接口即可傻昙,然后就可以做出千變?nèi)f化的動(dòng)畫效果了闺骚。具體而言是:自定義插值器需要實(shí)現(xiàn) Interpolator 或者 TimeInterpolator ,自定義估值算法需要實(shí)現(xiàn) TypeEvaluator 妆档。如果要對其他類型(非int,float,color)做動(dòng)畫僻爽,必須要自定義類型估值算法。

3贾惦、屬性動(dòng)畫的監(jiān)聽器

屬性動(dòng)畫提供了監(jiān)聽器用于監(jiān)聽動(dòng)畫的播放過程胸梆,主要有如下兩個(gè)接口:AnimatorUpdateListener 和 AnimatorListener 敦捧。

public static interface AnimatorListener {
void onAnimationStart(Animator animation); //動(dòng)畫開始
void onAnimationEnd(Animator animation); //動(dòng)畫結(jié)束
void onAnimationCancel(Animator animation); //動(dòng)畫取消
void onAnimationRepeat(Animator animation); //動(dòng)畫重復(fù)播放
}

為了方便開發(fā),系統(tǒng)提供了AnimatorListenerAdapter類碰镜,它是AnimatorListener的適配器類兢卵,可以有選擇的實(shí)現(xiàn)以上4個(gè)方法。

public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}

AnimatorUpdateListener會(huì)監(jiān)聽整個(gè)動(dòng)畫的過程绪颖,動(dòng)畫由許多幀組成的秽荤,每播放一幀,onAnimationUpdate就會(huì)調(diào)用一次柠横。利用這個(gè)特性窃款,我們可以做一些特殊的事情。

4牍氛、對任意屬性做動(dòng)畫

屬性動(dòng)畫原理:屬性動(dòng)畫要求動(dòng)畫作用的對象提供 get 方法和 set 方法晨继,屬性動(dòng)畫根據(jù)外界傳遞該屬性的初始值和最終值以動(dòng)畫的效果去多次調(diào)用 set 方法,每次傳遞給 set 方法的值都不一樣搬俊,確切的來說是隨著時(shí)間的推移紊扬,所傳遞的值越來越接近最終值∮颇ǎ總結(jié)一下珠月,我們對 object 對象屬性 abc 做動(dòng)畫,如果想要?jiǎng)赢嬌ǖ校瑫r(shí)滿足兩個(gè)條件:

  • object 必須要提供 setAbc() 方法啤挎,如果動(dòng)畫的時(shí)候沒有傳遞初始值,那么還要提供 getAbc() 方法卵凑,因?yàn)橄到y(tǒng)要去取 abc 屬性的初始值(如果這條不滿足庆聘,程序直接crash)。
  • object 的 setAbc() 對屬性 abc 所做的改變必須能夠通過某種方法反應(yīng)出來(即最終體現(xiàn)了 UI 的變化)勺卢,比如會(huì)帶來 UI 的改變之類(如果這條不滿足伙判,動(dòng)畫無效果,但是程序不會(huì)crash)黑忱。

我們給 Button 的 width 屬性做動(dòng)畫無效果但是沒有crash的原因就是 Button 內(nèi)部提供了 setWidth 和 getWidth 方法宴抚,但是這個(gè) setWidth 方法并不是改變 UI 大小的,而是用來設(shè)置最大寬度和最小寬度的甫煞。對于上面屬性動(dòng)畫的兩個(gè)條件來說菇曲,這個(gè)例子只滿足了條件 1 而未滿足條件 2。

針對上面問題抚吠,官方文檔給出了 3 種解決方法:

  • 請給你的對象加上get和set方法常潮,如果你有權(quán)限的話
    對于SDK或者其他第三方類庫的類無法加上的
  • 用一個(gè)類來包裝原始對象,間接為其提供get和set方法
 /**
  * 將 Button 沿著 X 軸方向放大
  * @param button
  */
private void performAnimationByWrapper(View button){
     ViewWrapper viewWrapper=new ViewWrapper(button);
     ObjectAnimator.ofInt(viewWrapper,"width",800)
        .setDuration(5000)
        .start();
}
 
private class ViewWrapper {
    private View targetView;
    public ViewWrapper(View targetView) {
        this.targetView = targetView;
    }
    public int getWidth() {
        //注意調(diào)用此函數(shù)能得到 View 的寬度的前提是楷力, View 的寬度是精準(zhǔn)測量模式喊式,即不可以是 wrap_content
        //否則得不到正確的測量值
        return targetView.getLayoutParams().width;
    }
    public void setWidth(int width) {
        //重寫設(shè)置目標(biāo) view 的布局參數(shù)孵户,使其改變大小
        targetView.getLayoutParams().width = width;
        //view 大小改變需要調(diào)用重新布局
        targetView.requestLayout();
    }
}
  • 采用ValueAnimator,監(jiān)聽動(dòng)畫過程岔留,自己實(shí)現(xiàn)屬性的改變
    ValueAnimator 本身不作用于任何對象夏哭,也就是說直接使用它沒有任何動(dòng)畫效果(所以系統(tǒng)提供了它的子類 ObjectAnimator 供我們直接使用,作用于對象直接執(zhí)行動(dòng)畫效果献联,而 ValueAnimator 只是提供改變一個(gè)值的過程方庭,并能監(jiān)聽到整個(gè)值的改變過程,我們基于這個(gè)過程可以自己去實(shí)現(xiàn)動(dòng)畫效果酱固,在這個(gè)過程中做想要達(dá)到的效果,自己去實(shí)現(xiàn))头朱。它可以對一個(gè)值做動(dòng)畫运悲,然后我們可以監(jiān)聽其動(dòng)畫過程,在動(dòng)畫過程中修改我們對象的屬性项钮,這樣我們自己就實(shí)現(xiàn)了對對象做了動(dòng)畫班眯。
 //new 一個(gè)整型估值器,用于下面比例值計(jì)算使用(可以自己去計(jì)算烁巫,這里直接使用系統(tǒng)的)
 private IntEvaluator intEvaluator = new IntEvaluator();
 private void performAnimatorByValue(final View targetView, final int start, final int end) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            //獲取當(dāng)前動(dòng)畫進(jìn)度值
            int currentValue = (int) animation.getAnimatedValue();
            //獲取當(dāng)前進(jìn)度占整個(gè)動(dòng)畫比例
            int fraction = (int) animation.getAnimatedFraction();
            //直接通過估值器根據(jù)當(dāng)前比例計(jì)算當(dāng)前 View 的寬度,然后設(shè)置給 View
            targetView.getLayoutParams().width = intEvaluator.evaluate(fraction, start, end);
            targetView.requestLayout();
        }
    });
    valueAnimator.setDuration(5000)
        .start();
 }

5署隘、屬性動(dòng)畫的工作原理

屬性動(dòng)畫需要運(yùn)行在有Looper的線程中,系統(tǒng)通過反射調(diào)用被作用對象get/set方法亚隙。

四磁餐、使用動(dòng)畫的注意事項(xiàng)

  • OOM問題
    使用幀動(dòng)畫時(shí),當(dāng)圖片數(shù)量較多且圖片分辨率較大的時(shí)候容易出現(xiàn)OOM阿弃,需注意诊霹,盡量避免使用幀動(dòng)畫。
  • 內(nèi)存泄漏
    使用無限循環(huán)的屬性動(dòng)畫時(shí)渣淳,在Activity退出時(shí)即使停止脾还,否則將導(dǎo)致Activity無法釋放從而造成內(nèi)存泄露。
  • 兼容性問題
    動(dòng)畫在3.0以下的系統(tǒng)存在兼容性問題入愧,特殊場景可能無法正常工作鄙漏,需做好適配工作。
  • View動(dòng)畫的問題
    View動(dòng)畫是對View的影像做動(dòng)畫棺蛛,并不是真正的改變了View的狀態(tài)怔蚌,因此有時(shí)候會(huì)出現(xiàn)動(dòng)畫完成后View無法隱藏( setVisibility(View.GONE) 失效) ,這時(shí)候調(diào)用 view.clearAnimation() 清理View動(dòng)畫即可解決鞠值。
  • 不要使用px
    使用px會(huì)導(dǎo)致不同設(shè)備上有不同的效果媚创。
  • 動(dòng)畫元素的交互
    View動(dòng)畫是對View的影像做動(dòng)畫,View的真實(shí)位置沒有變動(dòng)彤恶,動(dòng)畫完成后的新位置是無法觸發(fā)點(diǎn)擊事件的钞钙。屬性動(dòng)畫是真實(shí)改變了View的屬性鳄橘,所以動(dòng)畫完成后的位置可以接受觸摸事件。
  • 硬件加速
    使用動(dòng)畫的過程中芒炼,使用硬件加速可以提高動(dòng)畫的流暢度瘫怜。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市本刽,隨后出現(xiàn)的幾起案子鲸湃,更是在濱河造成了極大的恐慌,老刑警劉巖子寓,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暗挑,死亡現(xiàn)場離奇詭異,居然都是意外死亡斜友,警方通過查閱死者的電腦和手機(jī)炸裆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲜屏,“玉大人烹看,你說我怎么就攤上這事÷迨罚” “怎么了惯殊?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長也殖。 經(jīng)常有香客問我土思,道長,這世上最難降的妖魔是什么忆嗜? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任浪漠,我火速辦了婚禮,結(jié)果婚禮上霎褐,老公的妹妹穿的比我還像新娘址愿。我一直安慰自己,他們只是感情好冻璃,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布响谓。 她就那樣靜靜地躺著,像睡著了一般省艳。 火紅的嫁衣襯著肌膚如雪娘纷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天跋炕,我揣著相機(jī)與錄音赖晶,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遏插,可吹牛的內(nèi)容都是我干的捂贿。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼胳嘲,長吁一口氣:“原來是場噩夢啊……” “哼厂僧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起了牛,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤颜屠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鹰祸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甫窟,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年蛙婴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蕴坪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敬锐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呆瞻,到底是詐尸還是另有隱情台夺,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布痴脾,位于F島的核電站颤介,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赞赖。R本人自食惡果不足惜滚朵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望前域。 院中可真熱鬧辕近,春花似錦、人聲如沸匿垄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽椿疗。三九已至漏峰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間届榄,已是汗流浹背浅乔。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铝条,地道東北人靖苇。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓席噩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顾复。 傳聞我的和親對象是個(gè)殘疾皇子班挖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容