App開發中三種動畫使用和屬性詳解
本文轉載自微信公眾號「Android開發編程」,作者Android開發編程。轉載本文請聯系Android開發編程公眾號。
前言
這次我們介紹一下android中動畫的分類:
View Animation(補間動畫);
Drawable Animation(幀動畫);
Property Animation(屬性動畫);
一、幀動畫
幀動畫是順序播放一組預先定義好的圖片,不同于View動畫,系統提供了另外一個類AnimationDrawable來使用幀動畫;
幀動畫顧名思義就是通過順序一幀一幀播放圖片從而產生動畫效果,效果類似放電影;
該動畫缺點比較明顯,就是如果圖片過大過多會導致OOM。幀動畫xml文件放置在drawable目錄下而非anim文件夾下;
幀動畫的使用
首先我們找一組幀動畫的圖片放入drawable-xhdpi文件夾下,其次在drawable文件夾下創建xml文件,如下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <animation-list
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:oneshot="false">
- <item android:drawable="@drawable/refresh1" android:duration="180"/>
- <item android:drawable="@drawable/refresh2" android:duration="180"/>
- ...
- <item android:drawable="@drawable/refresh25" android:duration="180"/>
- </animation-list>
- view = findViewById(R.id.test);
- view.setBackgroundResource(R.drawable.drawable_test_anim);
- view.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- AnimationDrawable animationDrawable = (AnimationDrawable) view.getBackground();
- animationDrawable.start();
- }
- });
屬性介紹
- <animation-list> 必須是根節點,包含一個或者多個<item>元素,屬性有:
- android:oneshot true代表只執行一次,false循環執行;
- <item> 類似一幀的動畫資源;
- <item> animation-list的子項,包含屬性如下:
- android:drawable 一個frame的Drawable資源;
- android:duration 一個frame顯示多長時間;
二、補間動畫
補間動畫是通過對view進行旋轉、縮放、漸變、透明度變化,而達到的一種動畫效果;
是一種漸進式動畫。并且可以通過組合以上四種操作,完成復雜的自定義動畫效果;
缺點就是只是改變的view的展示狀態,但是不會改變view的位置;
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android"
- android:duration="4000"
- android:fillAfter="true"
- android:fillBefore="true"
- android:interpolator="@[package:]anim/interpolator_resource"
- android:repeatMode="restart | reverse"
- android:repeatCount = “0”
- android:shareInterpolator="true"
- android:startOffset="float">
- <alpha
- android:fromAlpha="float"
- android:toAlpha="float" />
- <scale
- android:fromXScale="float"
- android:fromYScale="float"
- android:pivotX="float"
- android:pivotY="float"
- android:toXScale="float"
- android:toYScale="float" />
- <rotate
- android:fromDegrees="float"
- android:pivotX="float"
- android:pivotY="float"
- android:toDegrees="float" />
- <translate
- android:fromXDelta="float"
- android:fromYDelta="float"
- android:toXDelta="float"
- android:toYDelta="float" />
- </set>
通用屬性說明:
- android:duration=""動畫時長,單位毫秒
- android:fillAfter="true"動畫完成后是否停留在結束位置,默認false
- android:fillBefore="true"動畫完成后是否停留在起點位置。默認true,優先級低于fillAfter
- android:interpolator為動畫的變化速度【可以單獨設置,可以直接放在set里面】
- android:repeatMode="restart | reverse"動畫重復策略 restart從起點位置(正序)重復,reverse從結束位置(倒序)重復
- android:repeatCount = “0”重復次數 “infinite”為無線重復
- android:shareInterpolator="true"動畫集合中的動畫是否公用一個差值器
- android:startOffset="float"動畫延遲時間
透明度動畫
- 透明度動畫,通過改變view的透明度展示動畫。對應AlphaAnimation和
xml標簽 - android:fromAlpha="float" 起始透明度,取值范圍(-1.0~1.0)
- android:toAlpha="float"結束時透明度,取值范圍(-1.0~1.0)
縮放動畫
- 縮放動畫,通過修改view的大小展示動畫。對應ScaleAnimation類和
xml表情 - android:fromXScale="float"動畫在水平方向X的起始縮放倍數
- android:fromYScale="float"動畫在水平方向Y的結束縮放倍數
- android:toXScale="float"動畫在豎直方向X的結束縮放倍數
- android:toYScale="float"動畫在豎直方向Y的結束縮放倍數
- android:pivotX="float"縮放中心點的x坐標
- android:pivotY="float"縮放中心點的y坐標
旋轉動畫
- 通過旋轉view展示動畫。對應RotateAnimation類和
xml標簽 - android:fromDegrees="float"動畫開始時 視圖的旋轉角度(正數 = 順時針,負數 = 逆時針)
- android:toDegrees="float"動畫結束時 視圖的旋轉角度(正數 = 順時針,負數 = 逆時針)
- android:pivotX="float"旋轉中心點的x坐標 具體如上縮放中心點參數解釋
- android:pivotY="float"旋轉中心點的y坐標 具體如上縮放中心點參數解釋
平移動畫
- 平移動畫,更改view的展示位置展示動畫。對應TranslateAnimation類和
xml表情 - android:fromXDelta="float"view在水平x方向的起始值
- android:fromYDelta="float"view在水平y方向的起始值
- android:toXDelta="float"view在水平x方向的結束值
- android:toYDelta="float" view在水平y方向的結束值
具體動畫的使用
應用動畫xml配置
- TextView textDemo = findViewById(R.id.text_demo);
- Animation animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_animation_test);
- textDemo.startAnimation(animation);
使用java類配置動畫,具體參數類同xml參數,建議使用xml配置動畫
- AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 2.0f);
- textDemo.startAnimation(alphaAnimation);
監聽動畫
- alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- //動畫開始回調
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- //動畫結束回調
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- //動畫重復時回調
- }
- });
三、屬性動畫
屬性動畫本質是通過改變對象的屬性(例如:x,y等屬性),來實現動畫的,所以基本上是無所不能的,只要對象有這個屬性,就能實現動畫效果;
屬性動畫是在api 11的新特性,通過動態的改變view的屬性從而達到動畫效果。雖然可以使用nineoldandroid庫向下兼容,但是兼容本質是使用補間動畫完成,也就是說不會更改view的屬性,也不會更改view的位置;
屬性動畫比較常用的類:ValueAnimator、ObjectAnimator、AnimationSet,其中ObjectAnimator是ValueAnimator的子類,而AnminationSet是動畫集合;
1.單個動畫
- ObjectAnimator animator = ObjectAnimator
- .ofInt(textDemo, "backgroundColor", 0XffFF0000, 0Xff0000FF)
- .setDuration(2000);
- animator.setRepeatMode(ValueAnimator.RESTART);
- animator.setRepeatCount(10);
- animator.start();
2.動畫集合
- AnimatorSet animatorSet = new AnimatorSet();
- ValueAnimator translationX = ObjectAnimator.ofFloat(textDemo, "translationX", 200f);
- ValueAnimator animator = ObjectAnimator
- .ofInt(textDemo, "backgroundColor", 0XffFF0000, 0Xff0000FF);
- animatorSet.playTogether(translationX,animator);
- animatorSet.setDuration(1000).start();
動畫配置同樣可以使用xml配置;
3.差值器和估值器
差值器(Interpolator)
根據時間流逝百分比計算當前屬性改變百分比。同xml配置動畫中的 android:interpolator屬性配置,常見有LinearInterpolator(線性差值器)、AccelerateDecelerateInterpolator(加速減速差值器)等。自定義需要實現Interpolator或者TimeInterpolator。Interpolator接口繼承TimeInterpolator;
- // Interpolator接口
- public interface Interpolator extends TimeInterpolator{
- // 內部只有一個方法
- float getInterpolation(float input) {
- // 參數說明
- // input值值變化范圍是0-1,且隨著動畫進度(0% - 100% )均勻變化
- // 即動畫開始時,input值 = 0;動畫結束時input = 1
- // 而中間的值則是隨著動畫的進度(0% - 100%)在0到1之間均勻增加
- ...// 插值器的計算邏輯
- return xxx;
- // 返回的值就是用于估值器繼續計算的fraction值,下面會詳細說明
- }
- // TimeInterpolator接口
- // 同上
- public interface TimeInterpolator {
- float getInterpolation(float input);
- }
估值器(TypeEvaluator)
根據當前屬性改變百分比計算改變后的屬性值。屬性動畫特有的屬性;自定義估值器需要實現TypeEvaluator接口;
- public interface TypeEvaluator {
- public Object evaluate(float fraction, Object startValue, Object endValue) {
- // 參數說明
- // fraction:插值器getInterpolation()的返回值
- // startValue:動畫的初始值
- // endValue:動畫的結束值
- ....// 估值器的計算邏輯
- return xxx;
- // 賦給動畫屬性的具體數值
- // 使用反射機制改變屬性變化
可以對任意屬性做屬性動畫,屬性動畫要求動畫作用的對象提供該屬性的get()和set()方法。因為屬性動畫本質就是根據外界傳遞的對象屬性的初始值和終點值,然后根據估值器和差值器計算屬性值,不斷調用屬性的set方法,通過時間的推移所傳遞的值,越來越近終點值;
注意:
對象屬性必須提供對應的set方法,而且如果沒有初始值傳入的情況下必須要設置get方法,因為 系統要獲取初始值,如果沒有滿足條件則程序cash;
對象屬性的set方法對屬性做出改變,需要能夠通過某種方法表示出來。帶來ui展示效果的改變。否則動畫不會生效;
ValueAnimator
使用ValueAnimator通過監聽動畫過程,自己改變對象屬性完成動畫
- ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
- valueAnimator.setDuration(2000);//動畫持續時間
- valueAnimator.setRepeatCount(0);//重復次數
- valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//重復方式,
- valueAnimator.setStartDelay(20);//開始前延遲時間
- valueAnimator.setEvaluator(new IntEvaluator());//估值器
- valueAnimator.setInterpolator(new LinearInterpolator());//差值器
- valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- //獲取當前動畫屬性值,即1~100
- Integer animatedValue = (Integer) animation.getAnimatedValue();
- //獲取動畫的百分比
- float animatedFraction = animation.getAnimatedFraction();
- ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
- int width = layoutParams.width;
- int height = layoutParams.height;
- layoutParams.height = height + 1;
- layoutParams.width=width+1;
- Log.e(TAG,"animatedValue: "+animatedValue+" animatedFraction : "+animatedFraction
- +" width : "+layoutParams.width+" height : "+layoutParams.height);
- textView.requestLayout();
- }
- });
- valueAnimator.start();
- }
四、注意事項
OOM注意,在幀動畫中如果圖片過大、數量過多容易出現;
內存泄漏, 切記在activity銷毀時,停止動畫。否則一些無限循環動畫將導致activity不能釋放而內存泄漏。出現在屬性動畫中,view動畫不存在此類問題;
View動畫即補間動畫,是改變view的視覺位置,改變view的影像展示位置,而不改變真實位置;注意交互體驗。可能會出現view動畫結束后,view無法隱藏的問題及setVisibility(View.GONE)失效。此時調用view.clearAnimation()清除動畫。可修復此類問題;
總結
公眾號里面是系統的總結,但是要系統學習一類的知識點了,又不是很好;
于是就想寫個小冊-掘金小冊,這樣老鐵們就可以系統的學習某個知識點了;