从零开始学Android自定义View之动画系列——属性动画(2)
組合動(dòng)畫
獨(dú)立的動(dòng)畫能夠?qū)崿F(xiàn)的視覺效果畢竟是相當(dāng)有限的,因此將多個(gè)動(dòng)畫組合到一起播放就顯得尤為重要。幸運(yùn)的是,Android團(tuán)隊(duì)在設(shè)計(jì)屬性動(dòng)畫的時(shí)候也充分考慮到了組合動(dòng)畫的功能,因此提供了一套非常豐富的API來讓我們將多個(gè)動(dòng)畫組合到一起。
實(shí)現(xiàn)組合動(dòng)畫功能主要需要借助AnimatorSet這個(gè)類,這個(gè)類提供了一個(gè)play()方法,如果我們向這個(gè)方法中傳入一個(gè)Animator對(duì)象(ValueAnimator或ObjectAnimator)將會(huì)返回一個(gè)AnimatorSet.Builder的實(shí)例,AnimatorSet.Builder中包括以下四個(gè)方法:
? after(Animator anim) 將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之后執(zhí)行
? after(long delay) 將現(xiàn)有動(dòng)畫延遲指定毫秒后執(zhí)行
? before(Animator anim) 將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之前執(zhí)行
? with(Animator anim) 將現(xiàn)有動(dòng)畫和傳入的動(dòng)畫同時(shí)執(zhí)行
好的,有了這四個(gè)方法,我們就可以完成組合動(dòng)畫的邏輯了,那么比如說我們想要讓TextView先從屏幕外移動(dòng)進(jìn)屏幕,然后開始旋轉(zhuǎn)360度,旋轉(zhuǎn)的同時(shí)進(jìn)行淡入淡出操作,就可以這樣寫:
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textView,"translatationX",-500f,0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(textView,"rotation",0f,360f); ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textView,"alpha",1f,0f,1f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(moveIn).with(rotate).after(fadeInOut); animatorSet.setDuration(5000); animatorSet.start();可以看到,這里我們先是把三個(gè)動(dòng)畫的對(duì)象全部創(chuàng)建出來,然后new出一個(gè)AnimatorSet對(duì)象之后將這三個(gè)動(dòng)畫對(duì)象進(jìn)行播放排序,讓旋轉(zhuǎn)和淡入淡出動(dòng)畫同時(shí)進(jìn)行,并把它們插入到了平移動(dòng)畫的后面,最后是設(shè)置動(dòng)畫時(shí)長(zhǎng)以及啟動(dòng)動(dòng)畫。運(yùn)行一下上述代碼,效果如下圖所示:
Animator監(jiān)聽器
在很多時(shí)候,我們希望可以監(jiān)聽到動(dòng)畫的各種事件,比如動(dòng)畫何時(shí)開始,何時(shí)結(jié)束,然后在開始或者結(jié)束的時(shí)候去執(zhí)行一些邏輯處理。這個(gè)功能是完全可以實(shí)現(xiàn)的,Animator類當(dāng)中提供了一個(gè)addListener()方法,這個(gè)方法接收一個(gè)AnimatorListener,我們只需要去實(shí)現(xiàn)這個(gè)AnimatorListener就可以監(jiān)聽動(dòng)畫的各種事件了。
大家已經(jīng)知道,ObjectAnimator是繼承自ValueAnimator的,而ValueAnimator又是繼承自Animator的,因此不管是ValueAnimator還是ObjectAnimator都是可以使用addListener()這個(gè)方法的。另外AnimatorSet也是繼承自Animator的,因此addListener()這個(gè)方法算是個(gè)通用的方法。
添加一個(gè)監(jiān)聽器的代碼如下所示:
anim.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {} });可以看到,我們需要實(shí)現(xiàn)接口中的四個(gè)方法,onAnimationStart()方法會(huì)在動(dòng)畫開始的時(shí)候調(diào)用,onAnimationRepeat()方法會(huì)在動(dòng)畫重復(fù)執(zhí)行的時(shí)候調(diào)用,onAnimationEnd()方法會(huì)在動(dòng)畫結(jié)束的時(shí)候調(diào)用,onAnimationCancel()方法會(huì)在動(dòng)畫被取消的時(shí)候調(diào)用。
但是也許很多時(shí)候我們并不想要監(jiān)聽那么多個(gè)事件,可能我只想要監(jiān)聽動(dòng)畫結(jié)束這一個(gè)事件,那么每次都要將四個(gè)接口全部實(shí)現(xiàn)一遍就顯得非常繁瑣。沒關(guān)系,為此Android提供了一個(gè)適配器類,叫作AnimatorListenerAdapter,使用這個(gè)類就可以解決掉實(shí)現(xiàn)接口繁瑣的問題了,如下所示:
這里我們向addListener()方法中傳入這個(gè)適配器對(duì)象,由于AnimatorListenerAdapter中已經(jīng)將每個(gè)接口都實(shí)現(xiàn)好了,所以這里不用實(shí)現(xiàn)任何一個(gè)方法也不會(huì)報(bào)錯(cuò)。那么如果我想監(jiān)聽動(dòng)畫結(jié)束這個(gè)事件,就只需要單獨(dú)重寫這一個(gè)方法就可以了,如下所示:
anim.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);} });使用XML編寫動(dòng)畫
過去的補(bǔ)間動(dòng)畫除了使用代碼編寫之外也是可以使用XML編寫的,因此屬性動(dòng)畫也提供了這一功能,即通過XML來完成和代碼一樣的屬性動(dòng)畫功能。
通過XML來編寫動(dòng)畫可能會(huì)比通過代碼來編寫動(dòng)畫要慢一些,但是在重用方面將會(huì)變得非常輕松,比如某個(gè)將通用的動(dòng)畫編寫到XML里面,我們就可以在各個(gè)界面當(dāng)中輕松去重用它。
如果想要使用XML來編寫動(dòng)畫,首先要在res目錄下面新建一個(gè)animator文件夾,所有屬性動(dòng)畫的XML文件都應(yīng)該存放在這個(gè)文件夾當(dāng)中。然后在XML文件中我們一共可以使用如下三種標(biāo)簽:
那么比如說我們想要實(shí)現(xiàn)一個(gè)從0到100平滑過渡的動(dòng)畫,在XML當(dāng)中就可以這樣寫:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="0" android:valueTo="100" android:valueType="intType"/>而如果我們想將一個(gè)視圖的alpha屬性從1變成0,就可以這樣寫:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="1" android:valueTo="0" android:valueType="floatType" android:propertyName="alpha"/>其實(shí)XML編寫動(dòng)畫在可讀性方面還是挺高的,上面的內(nèi)容相信不用我做解釋大家也都看得懂吧。
另外,我們也可以使用XML來完成復(fù)雜的組合動(dòng)畫操作,比如將一個(gè)視圖先從屏幕外移動(dòng)進(jìn)屏幕,然后開始旋轉(zhuǎn)360度,旋轉(zhuǎn)的同時(shí)進(jìn)行淡入淡出操作,就可以這樣寫:
這段XML實(shí)現(xiàn)的效果和我們剛才通過代碼來實(shí)現(xiàn)的組合動(dòng)畫的效果是一模一樣的,每個(gè)參數(shù)的含義都非常清楚,相信大家都是一看就懂,我就不再一一解釋了。
最后XML文件是編寫好了,那么我們?nèi)绾卧诖a中把文件加載進(jìn)來并將動(dòng)畫啟動(dòng)呢?只需調(diào)用如下代碼即可:
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file); animator.setTarget(view); animator.start();調(diào)用AnimatorInflater的loadAnimator來將XML動(dòng)畫文件加載進(jìn)來,然后再調(diào)用setTarget()方法將這個(gè)動(dòng)畫設(shè)置到某一個(gè)對(duì)象上面,最后再調(diào)用start()方法啟動(dòng)動(dòng)畫就可以了,就是這么簡(jiǎn)單。
總結(jié)
以上是生活随笔為你收集整理的从零开始学Android自定义View之动画系列——属性动画(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux Qt打包应用程序--利用li
- 下一篇: 企业网站 源码 服务邮箱:_企业网站建设