安卓基本動畫的使用及詳解

安卓基本動畫的使用及詳解

每次使用到動畫就感覺既熟悉又陌生,只知道大概流程,用到具體的方法,只知道有這樣的一個方法,但是又不知到怎樣調用出來,最終還是要行百度搜索一下資源,讓後複製到項目中,下次使用時 依然會忘記,所以這裏寫一篇博客筆記,記錄一下,加深一下印象,希望以後用到動畫可以,隨手敲來.也希望對看這篇博客的小夥伴有所幫助.

安卓動畫的介紹

  • View Animation: 這個動畫是安卓一直都有的,但是它又一個侷限性,就是隻能用在View上面,不夠強大

  • Drawable Animation: 幀動畫,(也叫frame動畫),類似與GIF圖片,是將一組圖片,在極短的時間內連續播放,造成視覺錯誤,看着類似是在動,其實是一組靜態的圖片高速播放造成的效果

  • Animator 屬性動畫,這個是安卓3.0才加進來的(API 11)才添加進來的.這種動畫可以設置給Object(任何對象或者屬性)也是使用最多的一個動畫,支持擴展等非常靈活…

當前應用程序開發涉及的主要動畫也就這三大類,我們接下來以類別爲基礎來慢慢展開說明。

2 View Animation(視圖動畫)使用詳解

2.1視圖動畫又稱(補間.(twn)動畫)

可以在一個視圖容器內執行一系列簡單變換(位置、大小、旋轉、透明度)。譬如,如果你有一個TextView對象,您可以移動、旋轉、縮放、透明度設置其文本,當然,如果它有一個背景圖像,背景圖像會隨着文本變化。

補間動畫有兩種實現的方式,一種是以xml佈局文件實現的,一種是以代碼直接編輯實現,兩者均可,但是一佈局文件實現的,重用性高,代碼更加簡潔.但是要創建一個新的文件,所以大家視情況和喜好決定吧.

先來看一下補間動畫有幾種,以下是補間動畫的集成關係
這裏寫圖片描述

java類名 關鍵字及目錄 動畫描述
AlphaAnimation 放置在res/anim/目錄下 漸變透明度動畫效果
RotateAnimation 放置在res/anim/目錄下 畫面轉移旋轉動畫效果
ScaleAnimation 放置在res/anim/目錄下 漸變尺寸伸縮動畫效果
TranslateAnimation 放置在res/anim/目錄下 畫面轉換位置移動動畫效果
AnimationSet 放置在res/anim/目錄下 一個持有其它動畫元素alpha、scale、translate、rotate或者其它set元素的容器

先介紹第一種佈局文件實現:

xml屬性詳解

xml屬性 java方法 解釋
android:detachWallpaper setDetachWallpaper(boolean) 是否在壁紙上運行
android:duration setDuration(long) 動畫持續時間,毫秒爲單位
android:fillAfter setFillAfter(boolean) 控件動畫結束時是否保持動畫最後的狀態
android:fillBefore setFillBefore(boolean) 控件動畫結束時是否還原到開始動畫前的狀態
android:fillEnabled setFillEnabled(boolean) 與android:fillBefore效果相同
android:interpolator setInterpolator(Interpolator) 設定插值器(指定的動畫效果,譬如回彈,加速,減速等)
android:repeatCount setRepeatCount(int) 重複次數
android:repeatMode setRepeatMode(int) 重複類型有兩個值,reverse表示倒序回放,restart表示從頭播放
android:startOffset setStartOffset(long) 調用start函數之後等待開始運行的時間,單位爲毫秒
android:zAdjustment setZAdjustment(int) 表示被設置動畫的內容運行時在Z軸上的位置(top/bottom/normal),默認爲normal

以上是所有補間動畫都共同具備的屬性(方法).接下來介紹一下,不同的補間動畫,所獨自擁有的屬性(方法).

2.1.2 alpha(透明)的屬性

xml屬性 java方法 解釋
android:fromAlpha AlphaAnimation(float fromAlpha, …) 動畫開始的透明度(0.0到1.0,0.0是全透明,1.0是不透明)
android:toAlpha AlphaAnimation(…, float toAlpha) 動畫結束的透明度,同上

2.1.3 Rotate(旋轉)的屬性

xml屬性 java方法 解釋
android:fromDegrees RotateAnimation(float fromDegrees, …) 旋轉開始角度,正代表順時針度數,負代表逆時針度數
android:toDegrees RotateAnimation(…, float toDegrees, …) 旋轉結束角度,正代表順時針度數,負代表逆時針度數
android:pivotX RotateAnimation(…, float pivotX, …) 縮放起點X座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px爲初始點、50%表示以當前View的左上角加上當前View寬高的50%做爲初始點、50%p表示以當前View的左上角加上父控件寬高的50%做爲初始點)
android:pivotY RotateAnimation(…, float pivotY) 縮放起點Y座標,同上規律

2.1.4 Scale(縮放)屬性詳解

xml屬性 java方法 解釋
android:fromXScale ScaleAnimation(float fromX, …) 初始X軸縮放比例,1.0表示無變化
android:toXScale ScaleAnimation(…, float toX, …) 結束X軸縮放比例
android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y軸縮放比例
android:toYScale ScaleAnimation(…, float toY, …) 結束Y軸縮放比例
android:pivotX ScaleAnimation(…, float pivotX, …) 縮放起點X軸座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px爲初始點、50%表示以當前View的左上角加上當前View寬高的50%做爲初始點、50%p表示以當前View的左上角加上父控件寬高的50%做爲初始點)
android:pivotY ScaleAnimation(…, float pivotY) 縮放起點Y軸座標,同上規律

2.1.5 Translate屬性詳解

xml屬性 java方法 解釋
android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始點X軸座標(數值、百分數、百分數p,譬如50表示以當前View左上角座標加50px爲初始點、50%表示以當前View的左上角加上當前View寬高的50%做爲初始點、50%p表示以當前View的左上角加上父控件寬高的50%做爲初始點)
android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始點Y軸從標,同上規律
android:toXDelta TranslateAnimation(…, float toXDelta, …) 結束點X軸座標,同上規律
android:toYDelta TranslateAnimation(…, float toYDelta) 結束點Y軸座標,同上規律

2.1.6 AnimationSet詳解

AnimationSet繼承自Animation,是上面四種的組合容器管理類,沒有自己特有的屬性,他的屬性繼承自Animation,所以特別注意,當我們對set標籤使用Animation的屬性時會對該標籤下的所有子控件都產生影響。

2.17 下面爲啦複製方便給出一個簡單的代碼示例

佈局文件代碼:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:fillAfter="true"
    android:fillBefore="false"
    android:repeatCount="2"
    android:repeatMode="reverse">
    <!--設置在set中的屬性會對包含在set中的動畫全部生效   這裏設置了時間,和保留動畫後的位置,以及重複模式是,反轉-->
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0.5" />
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />
    <!--這裏是平移y軸自身高度的30%-->
    <translate
        android:repeatCount="2"
        android:toXDelta="20%"
        android:toYDelta="30%" />
    <scale
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="1.5 "
        android:toYScale="1.5" />
</set>

佈局的引用

  animationSet = (AnimationSet) AnimationUtils.loadAnimation(this, R.anim.set_animtion);
        imageView.startAnimation(animationSet);
  • 其中注意在set標籤下設置android:repeatCount=”2”雖然不報錯但是其實是無效的,重複的次數必須設置到子標籤中才會生效,其他在set標籤下寫的屬性,都是公用的,既子標籤相當於集成了 set裏面設置的屬性 android:repeatCount=”2”除外

這裏寫圖片描述

2.1.8 java代碼示例

             TranslateAnimation translateAnimation=new TranslateAnimation(0,100,0,100);
                translateAnimation.setDuration(2000);
                translateAnimation.setRepeatMode(Animation.REVERSE);
                translateAnimation.setRepeatCount(3);
                translateAnimation.setFillAfter(true);

                RotateAnimation rotateAnimation=new RotateAnimation(0,720);
                rotateAnimation.setDuration(2000);
                rotateAnimation.setRepeatMode(Animation.REVERSE);
                rotateAnimation.setRepeatCount(2);
                rotateAnimation.setFillAfter(true);
                AnimationSet animationSet=new AnimationSet(true);
                animationSet.addAnimation(rotateAnimation);
                animationSet.addAnimation(translateAnimation);

                imageView.startAnimation(animationSet);
  • 注意代碼方式實現道理跟佈局實現的累死, rotateAnimation.setRepeatCount(2);這個重複次數也是要分別設置到TranslateAnimation 和RotateAnimation 等上面,其他屬性如播放時長,重複模式等可以由AnimationSet 統一設置

2.1.9Animation還有如下一些比較實用的方法介紹:

Animation類的方法 解釋
reset() 重置Animation的初始化
cancel() 取消Animation動畫
start() 開始Animation動畫
setAnimationListener(AnimationListener listener) 給當前Animation設置動畫監聽
hasStarted() 判斷當前Animation是否開始
hasEnded() 判斷當前Animation是否結束

既然補間動畫只能給View使用,那就來看看View中和動畫相關的幾個常用方法吧,如下:

View類的常用動畫操作方法 解釋
startAnimation(Animation animation) 對當前View開始設置的Animation動畫
clearAnimation() 取消當View在執行的Animation動畫

2.2 視圖動畫Interpolator插值器詳解

2.2.1 插值器簡介

介紹補間動畫插值器之前我們先來看一幅圖,如下:
這裏寫圖片描述

可以看見其實各種插值器都是實現了Interpolator接口而已,同時可以看見系統提供了許多已經實現OK的插值器,具體如下:

java類 xml id值 描述
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 動畫始末速率較慢,中間加速
AccelerateInterpolator @android:anim/accelerate_interpolator 動畫開始速率較慢,之後慢慢加速
AnticipateInterpolator @android:anim/anticipate_interpolator 開始的時候從後向前甩
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 類似上面AnticipateInterpolator
BounceInterpolator @android:anim/bounce_interpolator 動畫結束時彈起
CycleInterpolator @android:anim/cycle_interpolator 循環播放速率改變爲正弦曲線
DecelerateInterpolator @android:anim/decelerate_interpolator 動畫開始快然後慢
LinearInterpolator @android:anim/linear_interpolator 動畫勻速改變
OvershootInterpolator @android:anim/overshoot_interpolator 向前彈出一定值之後回到原來位置
PathInterpolator 新增,定義路徑座標後按照路徑座標來跑。

2.2.2自定義代碼Interpolator

自定義的Interpolator 需要實現Interpolator接口
這裏在給一個(差值器)Interpolator計算的 鏈接

http://inloop.github.io/interpolator/

public class ddd implements Interpolator {
    float f;
    public ddd(float f){
        this.f=f;

    }
    @Override
    public float getInterpolation(float input) {

        return (float) (Math. pow(2, -10 * input) * Math.sin((input - f / 4) * (2 * Math.PI) / f) + 1);
    }
}

自定義佈局文件的 差值器 稍後補充

3-2 Drawable動畫詳細說明

我們依舊可以使用xml或者java方式實現幀動畫。但是推薦使用xml,具體如下:

必須是根節點,包含一個或者多個元素,屬性有:

android:oneshot true代表只執行一次,false循環執行。
<item> 類似一幀的動畫資源。

animation-list的子項,包含屬性如下:

android:drawable 一個frame的Drawable資源。
android:duration 一個frame顯示多長時間。

3-3 Drawable動畫實例演示

關於幀動畫相對來說比較簡單,這裏給出一個常規使用框架,如下:

定義幀動畫


<!-- 注意:rocket.xml文件位於res/drawable/目錄下 -->
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource_name"
        android:duration="integer" />
</animation-list>

oneshot 是動畫是否執行一次,給false 就會無限循環
duration 是沒張動畫的持續時長,不易過大,50~200爲佳
drawable 是每次播放的圖片

代碼加載(使用)幀動畫

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);

rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
rocketAnimation.start();

三 接下來是重點,也是使用最多的動畫(屬性動畫)

3.1.1這裏重點介紹屬性動畫的ObjectAnimator和ValueAnimator

看一下Animator的繼承關係
這裏寫圖片描述

這裏先介紹一下ObjectAnimator

先從最簡單的開始,平時用的比較多的 對 View的操作(平移,旋轉,透明,縮放)

ObjectAnimator的基本使用和基本方法參數解讀

設置方式一: java代碼設置

ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);  

// ofFloat()作用有兩個
// 1. 創建動畫實例
// 2. 參數設置:參數說明如下
// Object object:需要操作的對象
// String property:需要操作的對象的屬性
// float ....values:動畫初始值 & 結束值(不固定長度)
// 若是兩個參數a,b,則動畫效果則是從屬性的a值到b值
// 若是三個參數a,b,c,則則動畫效果則是從屬性的a值到b值再到c值
// 以此類推
// 至於如何從初始值 過渡到 結束值,同樣是由估值器決定,此處ObjectAnimator.ofFloat()是有系統內置的浮點型估值器FloatEvaluator,同ValueAnimator講解

anim.setDuration(500);
        // 設置動畫運行的時長

        anim.setStartDelay(500);
        // 設置動畫延遲播放時間

        anim.setRepeatCount(0);
        // 設置動畫重複播放次數 = 重放次數+1
        // 動畫播放次數 = infinite時,動畫無限重複

        anim.setRepeatMode(ValueAnimator.RESTART);
        // 設置重複播放動畫模式
        // ValueAnimator.RESTART(默認):正序重放
        // ValueAnimator.REVERSE:倒序回放

animator.start();  
// 啓動動畫

設置方法二:xml 佈局設置

  • 注: 在路徑 res/animator 的文件夾裏創建動畫效果.xml文件
 // ObjectAnimator 採用<animator>  標籤
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="1"   // 初始值
    android:valueTo="0"  // 結束值
    android:valueType="floatType"  // 變化值類型 :floatType & intType
    android:propertyName="alpha" // 對象變化的屬性名稱

/>

也可以以set 爲跟標籤,裏面嵌條一些不同的動畫,做成一個一個動畫集AnimatorSet

在java文件中使用該動畫

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.view_obg_alpha);  
// 載入XML動畫

animator.setTarget(view);  
// 設置動畫對象

animator.start();  
// 啓動動畫
  • a) alpha (透明動畫)
 ObjectAnimator alphaObj=ObjectAnimator.ofFloat(iv_cang,"alpha",0,1);
                // 操作的對象  操作的屬性(動畫屬性)  如何動畫
                alphaObj.setRepeatCount(1);//重複次數  實際播放次數是設置的次數+1
                alphaObj.setDuration(2000);//播放時長
                alphaObj.start();//啓動動畫

透明動畫效果圖ll/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

  • b) rotation(旋轉)動畫
  ObjectAnimator rotationAnmiator=ObjectAnimator.ofFloat(iv_cang,"rotation",0,360);
                rotationAnmiator.setDuration(2000);
                rotationAnmiator.start();

旋轉效果圖

  • c)scale (縮放動畫)
 ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(iv_cang,"scaleX",1,2,1);
                scaleAnimator.setDuration(2000);
                scaleAnimator.start();

縮放效果圖

  • d) translation(平移) 動畫
 ObjectAnimator translation = ObjectAnimator.ofFloat(iv_cang,"TranslationX",0,200);
                translation.setDuration(2000);
                translation.start();

平移效果圖這裏只是平移了水平方向

這裏列出基本的動畫的傳入的值代表的意思
屬性 作用 數值類型

Alpha 控制View的透明度 float
TranslationX 控制X方向的位移 float
TranslationY 控制Y方向的位移 float
ScaleX 控制X方向的縮放倍數 float
ScaleY 控制Y方向的縮放倍數 float
Rotation 控制以屏幕方向爲軸的旋轉度數 float
RotationX 控制以X軸爲軸的旋轉度數 float
RotationY 控制以Y軸爲軸的旋轉度數 float
  • 在ObjectAnimator.ofFloat()的第二個參數String property可傳入alpha、rotation、translationX 和 scaleY 等值
  • 還可以傳入什麼值呢這個第二個參數, 其實這個參數是可以傳入任意值的(即任意的字符串)

2.2.0 爲什嗎ObjectAnimator.offloat()方法的第二個參數可以傳入任意值呢?

  • ObjectAnimator 類 對 對象屬性值 進行改變從而實現動畫效果的本質是:通過不斷控制 值 的變化,再不斷 自動 賦給對象的屬性,從而實現動畫效果

  • 而 自動賦給對象的屬性的本質是調用該對象屬性的set() & get()方法進行賦值

  • 所以,ObjectAnimator.ofFloat(Object object, String property, float ….values)的第二個參數傳入值的作用是:讓ObjectAnimator類根據傳入的屬性名 去尋找 該對象對應屬性名的 set() & get()方法,從而進行對象屬性值的賦值,如上面的例子:

等看完下面這個例子你估計就會更加明白一點了.
//下面的例子是借鑑網上的,自己寫重複寫了一遍

2.2.1 實現自定義對象的動畫

主要實現兩個重要的步驟

  • 爲對象設置需要操作屬性的set() & get()方法
  • 通過實現TypeEvaluator類從而定義屬性變化的邏輯

現在我們介紹一下ObjectAnimator.ofObject()方法.

實現一個自定義圓的顏色漸變

  • 第一步 給自定義對象加上要用的get() set() 方法
    – 方法一:通過繼承 增加get() set() 方法
    – 方法二:通過自定義包裝類,設置對象的值
    這裏先講第一種方法,第二種方法稍後給出例子

MyView1.java

package qst.com.mydonghuahejidemo.MyView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by user on 2017/10/19.
 */

public class MyView1 extends View {
    public MyView1(Context context) {
        super(context);
        initPaint();
    }

    public MyView1(Context context,  @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

    Paint mPaint;
    String mColor="#00ff00";
//    定義設置Color的get() set 方法
    public String getColor(){
        return mColor;
    }
    public void setColor(String color){
        this.mColor=color;
        //將畫筆的顏色設置成 傳遞進來的顏色
        mPaint.setColor(Color.parseColor(color));
        invalidate();
        //調用重新繪製的方法,重新繪製,調用invalidate()其實相當於重新走了一遍onDraw()方法,重新繪製圖案.
    }

//自定義三部曲  onMeasure計算自己的大小  onLayout給自己的孩子指定位置  onDraw繪製自己最終的樣子
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    /**
     * 初始化畫筆
     */
    private void initPaint(){
//        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint=new Paint();
        mPaint.setStyle(Paint.Style.FILL);//模式是填充
        mPaint.setAntiAlias(true);//抗鋸齒
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //圓心  半徑  畫筆
        canvas.drawCircle(200,200,100,mPaint);

    }
}
  • 第二步 加入到佈局中並且在java文件中初始化(findViewById)
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
<qst.com.mydonghuahejidemo.MyView.MyView1
            android:id="@+id/myView1"
            android:layout_width="400dp"
            android:layout_height="200dp" />

        <Button
            android:id="@+id/btn_color"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="小球變色" />
    </LinearLayout>
  • 第三步 自定義估值器(不是差值器)
    估值器是整個動畫過程中實際值的變化,差值器是計算值動畫的實際路線,兩者有聯繫,但不一樣

ColorEvaluator .java 實現顏色過渡的邏輯

package qst.com.mydonghuahejidemo.MyView;

import android.animation.TypeEvaluator;

public class ColorEvaluator implements TypeEvaluator {
    // 實現TypeEvaluator接口

    private int mCurrentRed;

    private int mCurrentGreen ;

    private int mCurrentBlue ;

    // 複寫evaluate()
    // 在evaluate()裏寫入對象動畫過渡的邏輯:此處是寫顏色過渡的邏輯
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {

        // 獲取到顏色的初始值和結束值
        String startColor = (String) startValue;
        String endColor = (String) endValue;

        // 通過字符串截取的方式將初始化顏色分爲RGB三個部分,並將RGB的值轉換成十進制數字
        // 那麼每個顏色的取值範圍就是0-255
        int startRed = Integer.parseInt(startColor.substring(1, 3), 16);
        int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);
        int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);

        int endRed = Integer.parseInt(endColor.substring(1, 3), 16);
        int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);
        int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);

        // 將初始化顏色的值定義爲當前需要操作的顏色值
            mCurrentRed = startRed;
            mCurrentGreen = startGreen;
            mCurrentBlue = startBlue;


        // 計算初始顏色和結束顏色之間的差值
        // 該差值決定着顏色變化的快慢:初始顏色值和結束顏色值很相近,那麼顏色變化就會比較緩慢;否則,變化則很快
        // 具體如何根據差值來決定顏色變化快慢的邏輯寫在getCurrentColor()裏.
        int redDiff = Math.abs(startRed - endRed);
        int greenDiff = Math.abs(startGreen - endGreen);
        int blueDiff = Math.abs(startBlue - endBlue);
        int colorDiff = redDiff + greenDiff + blueDiff;
        if (mCurrentRed != endRed) {
            mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,
                    fraction);
                    // getCurrentColor()決定如何根據差值來決定顏色變化的快慢 ->>關注1
        } else if (mCurrentGreen != endGreen) {
            mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,
                    redDiff, fraction);
        } else if (mCurrentBlue != endBlue) {
            mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,
                    redDiff + greenDiff, fraction);
        }
        // 將計算出的當前顏色的值組裝返回
        String currentColor = "#" + getHexString(mCurrentRed)
                + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);

        // 由於我們計算出的顏色是十進制數字,所以需要轉換成十六進制字符串:調用getHexString()->>關注2
        // 最終將RGB顏色拼裝起來,並作爲最終的結果返回
        return currentColor;
    }


    // 關注1:getCurrentColor()
    // 具體是根據fraction值來計算當前的顏色。

    private int getCurrentColor(int startColor, int endColor, int colorDiff,
                                int offset, float fraction) {
        int currentColor;
        if (startColor > endColor) {
            currentColor = (int) (startColor - (fraction * colorDiff - offset));
            if (currentColor < endColor) {
                currentColor = endColor;
            }
        } else {
            currentColor = (int) (startColor + (fraction * colorDiff - offset));
            if (currentColor > endColor) {
                currentColor = endColor;
            }
        }
        return currentColor;
    }

    // 關注2:將10進制顏色值轉換成16進制。
    private String getHexString(int value) {
        String hexString = Integer.toHexString(value);
        if (hexString.length() == 1) {
            hexString = "0" + hexString;
        }
        return hexString;
    }

}
  • 第四步 調用ObjectAnimtor.ofObject();設置動畫
  ObjectAnimator myView1Animator=ObjectAnimator.ofObject(myView1,"color",new ColorEvaluator(),"#00ff00","#ffffaa");
                myView1Animator.setDuration(3000);
                myView1Animator.start();

這樣一個自定義對象的動畫就完成了

球體顏色漸變

2.2.1 注意事項

  1. 假如對象必須要提供屬性a的set()方法
 1)假如你沒有給初始值,既ObjectAnimtor.ofObject()的最後一個可變的參數你只給了一個值,其實就是結束的值,這個時候系統會調用get方法,去獲取默認值,然後動畫就是從默認值開始做動畫的,如果沒有給get方法這個時候程序會直接爆炸,但是如果你給了  兩個貨兩個以上的值那麼get方法就可有可無,(建議寫上避免不必要的麻煩),
 2)加入你的可變參數只傳入一個值,即使你寫了get方法,但是如果你的默認值不合法,那麼程序也會崩潰,如上面小球的例子,顏色定義成了String 類型,如果你的默認值不是#000000這樣的格式,下面轉換的時候不能夠正確的轉換也會崩潰,請注意這兩點
 3) 如果你沒有提供set方法,那麼你直接調用ObjectAnimtor.ofObject(),程序不會崩潰,但是達不到動畫的效果,會沒有任何的反應

2.3.1 上面介紹了一個繼承原生的View對自定義View做了一個顏色漸變的操作, 下面這個介紹一個用封裝,做出對對象做動畫

例如我們要改變一個(View的寬度),我們調用setWindth();方法是沒有效果的,因爲View雖然有這樣的get() set() 方法,但是實際卻不是用來改變控件的寬度的,而是設置該View的 最大最小寬度

這裏直接給列子


 class FengWindth {
        int currentWindth;
        View mView;
        public FengWindth(View view){
            this.mView=view;
        }
        public int getWindth() {
            return mView.getLayoutParams().width;
        }
        public void setWindth(int windth) {
            this.currentWindth=windth;
            ViewGroup.LayoutParams params = mView.getLayoutParams();
            params.width=windth;
//            mView.requestLayout();
            mView.setLayoutParams(params);
        }
    }

使用:


ObjectAnimator obgWindth = ObjectAnimator.ofInt(new FengWindth(btn_windth), "windth", 300,600);
                obgWindth.setDuration(2000).start();

通過封裝,給View添加上setWidth()的方法

3 組合動畫(AnimatorSet 類)

3.1.1介紹

AnimatorSet 可以吧多個動畫,平移,旋轉,縮放,當人也包括自定義的等動畫結合在一起,
可以控制,同時播放,順序播放,延時播放,或者在某個動畫之後播放等:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章