Android26-動畫機(jī)制與使用技巧

Android View動畫

Animation 框架定義了透明度椎木、旋轉(zhuǎn)灭红、縮放和位移幾種常見的動畫为肮,而且控制的是整個View叉钥。

  • 以下是一些常用動畫的設(shè)置
  • 注意:View動畫改變的只是VIew的顯示效果罢缸,而不改變View的響應(yīng)區(qū)域
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void btnAlpha(View view) {
        AlphaAnimation aa = new AlphaAnimation(0, 1);
        aa.setDuration(3000);
        view.startAnimation(aa);
    }
    public void btnRotate(View view) {
        //0 :旋轉(zhuǎn)起始角度
        //360 : 旋轉(zhuǎn)終止角度
        //0,0 :繞那個點(diǎn)旋轉(zhuǎn)
        RotateAnimation ra = new RotateAnimation(0, 270, 0, 0);
        ra.setDuration(3000);
        view.startAnimation(ra);
    }
    public void btnRotateSelf(View view) {
        RotateAnimation ra = new RotateAnimation(0, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        ra.setDuration(3000);
        view.startAnimation(ra);
    }
    public void btnTranslate(View view) {
        //0 : x起始位置
        //200 :x結(jié)束位置
        //0 : y起始位置
        //300 :y結(jié)束位置
        TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
        ta.setDuration(3000);
        view.startAnimation(ta);
    }
    public void btnScale(View view) {
        //1 : x起始大小
        //1 : x結(jié)束大小
        //0 : y起始大小
        //2 : y結(jié)束大小
        ScaleAnimation sa = new ScaleAnimation(1, 1, 0, 2);
        sa.setDuration(3000);
        view.startAnimation(sa);
    }
    public void btnScaleSelf(View view) {
        ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        sa.setDuration(3000);
        view.startAnimation(sa);
    }
    public void btnSet(View view) {
        //動畫組
        AnimationSet as = new AnimationSet(true);
        as.setDuration(3000);
        //透明度動畫
        AlphaAnimation aa = new AlphaAnimation(0, 1);
        aa.setDuration(3000);
        as.addAnimation(aa);
        //平移動畫
        TranslateAnimation ta = new TranslateAnimation(0, 100, 0, 200);
        ta.setDuration(3000);
        as.addAnimation(ta);
        //啟動動畫
        view.startAnimation(as);
    }
}

Android屬性動畫

由于Animation框架改變的只是顯示效果投队,并不能相應(yīng)事件枫疆, 因此,在Android3.0之后引入了屬性動畫框架(Animator)敷鸦;Animator框架中使用最多的是AnimatorSet和ObjectAnimator的配合养铸。

  • ObjectAnimator

ObjectAnimator是屬性動畫框架中的最重要的實(shí)行類,創(chuàng)建一個ObjectAnimator只需通過他的靜態(tài)工廠類直接返回一個ObjectAnimator對象轧膘,參數(shù)包括一個對象和對象的屬性钞螟,但屬性必須有g(shù)et和set函數(shù)。

ObjectAnimator animator = ObjectAnimator.ofFloat(
      view,
      "translationX",
      300);
animator.setDuration(300);
animator.start();

ObjectAnimator : 常用動畫屬性說明

  • translationX 和 translationY :這兩個屬性通常用來控制view的平移谎碍。
  • rotaion鳞滨、rotationX、rotationY :這三個屬性控制view對象圍繞支點(diǎn)進(jìn)行2D和3D旋轉(zhuǎn)蟆淀。
  • scaleX 和 scaleY :這兩個屬性控制view對象圍繞它的支點(diǎn)進(jìn)行2D縮放拯啦。
  • pivotX 和 privotY :這兩個屬性控制view對象的支點(diǎn)位置,圍繞這個支點(diǎn)進(jìn)行旋轉(zhuǎn)和縮放變換處理熔任。默認(rèn)情況下褒链,該支點(diǎn)位置就是view對象的中心點(diǎn)。
  • x 和 y :這兩個屬性描述了view對象在它的容器中的最終位置疑苔,它是最初的做坐標(biāo)和tranlationX 和 translationY值的累計(jì)和甫匹。
  • alpha : 表示view對象的alpha透明度,默認(rèn)值是1(不透明)惦费,0代表完全透明(不可見)兵迅。

注:如果一個屬性沒有g(shù)et、set方法薪贫,也通過包裝類的方法給屬性增加get恍箭、set方法來實(shí)現(xiàn)動畫,代碼如下:

>     private static class WrapperView {
        private View mTarget;
        public WrapperView(View target) {
            mTarget = target;
        }
        public int getWidth() {
            return mTarget.getLayoutParams().width;
        }
        public void setWidth(int width) {
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }
    }

通過以上代碼瞧省,就給屬性提供了set扯夭、get方法鳍贾,使用時(shí)只需要操作包裝類即可

> WrapperView wrapper = new WrapperView(view);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(3000).start();
  • PropertyValuesHolder

類似視圖動畫的AnimationSet,屬性動畫如果對同個對象要定義多個屬性交洗,就要用刀PropertyValuesHolder來實(shí)現(xiàn)贾漏。

>  //同時(shí)操作多個屬性動畫
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(3000).start();
  • ValueAnimator

ValueAnimator在屬性動畫中占有非常重要的地位,他本身不提供任何動畫效果藕筋,他更像一個數(shù)值產(chǎn)生器纵散,用來產(chǎn)生具有一定規(guī)律的數(shù)字,從而讓調(diào)用者來控制動畫的實(shí)現(xiàn)過程隐圾。

> //ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0, 400);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
 @Override
 public void onAnimationUpdate(ValueAnimator animation) {
     Float value = (Float) animation.getAnimatedValue();
     //TODO use the value
     if (value < 200) {
         ObjectAnimator.ofFloat(view, "translationX", 200).setDuration(1000).start();
     } else {
         ObjectAnimator.ofFloat(view, "translationY", 200).setDuration(1000).start();
     }
 }
});
  • 動畫事件的監(jiān)聽

一個完整的動畫具有Start伍掀、Repeat、End暇藏、Cancel四個過程蜜笤,通過Android提供的API可以很方便的監(jiān)聽這四個事件

>         ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
       animator.addListener(new Animator.AnimatorListener() {
           @Override
           public void onAnimationStart(Animator animation) {
           //動畫開始時(shí)  
           }
           @Override
           public void onAnimationEnd(Animator animation) {
           //動畫結(jié)束時(shí)
           }
           @Override
           public void onAnimationCancel(Animator animation) {
           //動畫取消時(shí)
           }
           @Override
           public void onAnimationRepeat(Animator animation) {
           //動畫重復(fù)時(shí)
           }
       });
  • AnimatorSet

對于一個對象同時(shí)作用多個屬性動畫,可以用PropertyValuesHolder實(shí)現(xiàn)盐碱,同樣也可以用AnimatorSet實(shí)現(xiàn)把兔,而且AnimatorSet同時(shí)也能實(shí)現(xiàn)更為精確的順序控制。

>//使用AnimatorSet實(shí)現(xiàn)作用多個動畫
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();

AnimatorSet正是通過playTogether()瓮顽、playSequentially()县好、animSet.play().with()、before暖混、after()等方法來對多個動畫的播放順序做精確的控制的缕贡。

  • View的animate方法

在Android3.0之后,google給view增加了animate方法來直接設(shè)置屬性動畫拣播。代碼如下

>//通過view的animate方法直接設(shè)置屬性動畫
        view.animate().alpha(0).y(300).setDuration(3000).withStartAction(new Runnable() {
            @Override
            public void run() {
                //動畫開始時(shí)
            }
        }).withEndAction(new Runnable() {
            @Override
            public void run() {
                //動畫結(jié)束時(shí)
            }
        }).start();
    }

Android布局動畫

布局動畫晾咪,是指作用在ViewGroup上的動畫,當(dāng)ViewGroup增加view時(shí)添加一個動畫的過渡效果贮配。
最簡單的布局動畫是在ViewGroup的XML中谍倦,使用以下代碼來設(shè)置

android:animateLayoutChanges="true"

另外還可通過LayoutAnimationController類來自定義一個子View的過渡效果。

LinearLayout ll = (LinearLayout)findViewById(R.id.ll);
//設(shè)置過渡動畫
ScaleAnimation sa = new ScaleAnimation(0, 1, 0,1);
sa.setDuration(2000);
//設(shè)置布局動畫的顯示屬性
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
//為ViewGroup設(shè)置布局動畫
ll.setLayoutAnimation(lac);

LayoutAnimationController的第一個參數(shù)是需要作用的動畫泪勒,第二個參數(shù)是每個子view的顯示時(shí)間昼蛀,當(dāng)delay時(shí)間不為0時(shí)可以設(shè)置子view顯示的順序

  • LayoutAnimationController.ORDER_NORMAL--正序
  • LayoutAnimationController.ORDER_RANDOM -- 隨機(jī)
  • LayoutAnimationController.ORDER_REVERSE -- 反序
  • Interpolators(插值器)

通過插值器,可以定義動畫變換的速率酣藻,有點(diǎn)類似于物理中的加速度曹洽。主要作用是用來控制目標(biāo)變量的變化值然后進(jìn)行對應(yīng)的操作鳍置。

自定義動畫

創(chuàng)建自定義動畫辽剧,通常情況下只需要覆蓋父類的initialize方法來實(shí)現(xiàn)一些初始化工作,并且實(shí)現(xiàn)applyTransformation邏輯就可以了税产。

> public
class
CustomAnim extends Animation
{
   private int mCenterWidth;
   private int mCenterHeight;
   private Camera mCamera = new Camera();
   private float mRotateY = 0.0f;
   @Override
   public void initialize(int width, int height, int parentWidth, int parentHeight) {
       super.initialize(width, height, parentWidth, parentHeight);
       //設(shè)置默認(rèn)時(shí)長
       setDuration(2000);
       //設(shè)置動畫結(jié)束后保留狀態(tài)
       setFillAfter(true);
       //設(shè)置默認(rèn)插值器
       setInterpolator(new BounceInterpolator());
       mCenterHeight = height/2;
       mCenterWidth = width/2;
   }
   //暴漏一個接口給外界設(shè)置旋轉(zhuǎn)角度
   public void setRotateY(float rotateY) {
       mRotateY = rotateY;
   }
   @Override
   protected void applyTransformation(float interpolatedTime, Transformation t) {
       //獲得當(dāng)前的矩陣對象
       final Matrix matrix = t.getMatrix();
       mCamera.save();
       //使用Camera設(shè)置旋轉(zhuǎn)的角度
       mCamera.rotateY(mRotateY * interpolatedTime);
       //將旋轉(zhuǎn)變化作用到matrix上
       mCamera.getMatrix(matrix);
       mCamera.restore();
       //通過pre方法設(shè)置矩陣作用前的偏移量來改變旋轉(zhuǎn)中心
       matrix.preTranslate(mCenterWidth, mCenterHeight);
       matrix.postTranslate(-mCenterWidth, -mCenterHeight);
   }
}

在上面這個例子中用到了Camera怕轿,這里的Camera不是指手機(jī)中的相機(jī)偷崩,而是android.graphics.Camera中的Camera類,它封裝了openGL的3D動畫撞羽,從而可以非常方便的創(chuàng)建3D動畫效果阐斜。使用的時(shí)候就是通過設(shè)置三個坐標(biāo)軸(X、y诀紊、z)的旋轉(zhuǎn)角度谒出,從而實(shí)現(xiàn)3d動畫的效果

>mCamera.save();
//使用Camera設(shè)置旋轉(zhuǎn)的角度
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateZ(mRotateY * interpolatedTime);
//將旋轉(zhuǎn)變化作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();

SVG矢量動畫

SVG : 可伸縮適量圖形,于Bitmap(位圖)相比邻奠,最明顯的優(yōu)點(diǎn)是放大不會失真笤喳。

  • <path> 標(biāo)簽

使用<path>標(biāo)簽創(chuàng)建SVG,就像用指令的方式來控制一只畫筆碌宴,例如移動畫筆到某一坐標(biāo)位置杀狡,畫一條直線,畫一條曲線等贰镣。常用<path>指令有以下幾種:

  • M = moveto(M X, Y) : 將畫筆移動到指定的坐標(biāo)位置呜象,但未發(fā)生繪制。
  • L = lineto(L X, Y) : 畫直線到指定的坐標(biāo)位置
  • H = horizontal lineto(H X) : 畫水平線到指定的x坐標(biāo)位置碑隆。
  • V = vertical lineto(V Y) : 畫垂直線到指定的Y坐標(biāo)位置恭陡。
  • C = curveto(C X1, Y1, x2, Y2, ENDX, ENDY) : 三次貝塞爾曲線。
  • S = smooth curveto(S X2, Y2, ENDX, ENDY) : 三次貝塞爾曲線上煤。
  • Q = quadraic Belzier curve(Q X, Y, ENDX, ENDY) : 二次貝塞爾曲線子姜。
  • T = smooth quadratic Belzier curveto(T ENDX, ENDY) : 映射前面路徑后的終點(diǎn)。
  • A = cliptical Arc(A RX, RY, XROTATION, FLAG1, FLAG2, x, y) : 弧線楼入。
  • Z = closepath() : 關(guān)閉路徑哥捕。

注:使用這些指令需注意以下幾點(diǎn)

  • 坐標(biāo)軸以(0, 0) 為中心,X軸水平向右嘉熊, Y軸水平向下遥赚。
  • 所有指令大小寫均可,大寫表示絕對定位阐肤,參照全局坐標(biāo)系凫佛;小寫相對定位,參照父容器坐標(biāo)系孕惜。
  • 指令和數(shù)據(jù)間的空格可以省略愧薛。
  • 同一指令出現(xiàn)多次可以只用一個。
  • Android中使用SVG

Goggle在Android5.x中提供了VectorDrawable和AnimatedVectorDrawable兩個API來幫助支持SVG衫画,首先使用VectorDrawable來創(chuàng)建基于XML的SVG圖形毫炉,再結(jié)合AnimatedVectorDrawable來實(shí)現(xiàn)動畫效果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末削罩,一起剝皮案震驚了整個濱河市瞄勾,隨后出現(xiàn)的幾起案子费奸,更是在濱河造成了極大的恐慌,老刑警劉巖进陡,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愿阐,死亡現(xiàn)場離奇詭異,居然都是意外死亡趾疚,警方通過查閱死者的電腦和手機(jī)缨历,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糙麦,“玉大人戈二,你說我怎么就攤上這事≡剩” “怎么了觉吭?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長仆邓。 經(jīng)常有香客問我鲜滩,道長,這世上最難降的妖魔是什么节值? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任徙硅,我火速辦了婚禮,結(jié)果婚禮上搞疗,老公的妹妹穿的比我還像新娘嗓蘑。我一直安慰自己,他們只是感情好匿乃,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布桩皿。 她就那樣靜靜地躺著,像睡著了一般幢炸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宛徊,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天佛嬉,我揣著相機(jī)與錄音,去河邊找鬼闸天。 笑死暖呕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的苞氮。 我是一名探鬼主播震嫉,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼荔仁,長吁一口氣:“原來是場噩夢啊……” “哼画株!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抛姑,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤赞厕,失蹤者是張志新(化名)和其女友劉穎艳狐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體皿桑,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毫目,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诲侮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镀虐。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沟绪,靈堂內(nèi)的尸體忽然破棺而出刮便,到底是詐尸還是另有隱情,我是刑警寧澤绽慈,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布恨旱,位于F島的核電站,受9級特大地震影響坝疼,放射性物質(zhì)發(fā)生泄漏搜贤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一钝凶、第九天 我趴在偏房一處隱蔽的房頂上張望仪芒。 院中可真熱鬧,春花似錦耕陷、人聲如沸掂名。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铆隘。三九已至,卻和暖如春南用,著一層夾襖步出監(jiān)牢的瞬間膀钠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工裹虫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肿嘲,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓筑公,卻偏偏與公主長得像雳窟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

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

  • Animation Animation類是所有動畫(scale封救、alpha拇涤、translate、rotate)的基...
    四月一號閱讀 1,900評論 0 10
  • 屬性動畫簡介 Android開發(fā)過程中誉结,適當(dāng)?shù)氖褂靡恍﹦赢嬁梢宰屪约旱膽?yīng)用看起來更棒更炫鹅士。最初的時(shí)候Google為...
    AFinalStone閱讀 416評論 0 1
  • (本篇文章寫于2016年8月14日) 此時(shí)此刻我的30歲生日剛剛過去。所謂的30而立惩坑,并沒有什么特別大...
    超寫閱讀 495評論 1 5
  • 周末兩天掉盅,投身戶外公益領(lǐng)隊(duì)的學(xué)習(xí)中,報(bào)名參訓(xùn)是2年前職場迷茫之際的事兒以舒,一而再再而三的延遲參訓(xùn)趾痘,周末終于成...
    胡永群閱讀 737評論 0 49
  • 學(xué)習(xí)征信知識 維護(hù)自身權(quán)益 商丘市開展“信用記錄關(guān)愛日”宣傳活動 今年6月14日,是全國第十個“信...
    李淼rain閱讀 548評論 0 0