Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓學習筆記之動畫(下)

安卓學習筆記之動畫(下)

編輯:關於Android編程

一、內容概述

本篇側重講述屬性動畫 ,包含如下內容
- 屬性動畫

     - ObjectAnimator 的使用
     - ValueAnimator 的使用
     - PropertyValuesHolder 的使用
     - ViewPropertyAnimator 的使用
     - AnimatorSet的使用

- 插值器與估值器淺析

二、屬性動畫

屬性動畫概述

- 屬性動畫是在API11中加入的新特性,在android2.3以下可以使用nineoldandroids兼容庫。
- 屬性動畫是真實改變一個view的相關屬性。而view動畫不能改變一個view的真實屬性。
- 屬性動畫作用對象更加寬泛,不僅限於作用於view,甚至可以沒有作用的對象。

ViewPropertyAnimator的使用

1.示例

  @TargetApi(Build.VERSION_CODES.KITKAT)
    public void animate(View view) {
        final ViewPropertyAnimator animator = view.animate().x(200).y(300).alphaBy(-0.5f).rotationBy(60f).setInterpolator(new BounceInterpolator()).scaleXBy(0.3f).xBy(20).setDuration(2000);
        Log.e("TAG", view.getTranslationX() + " :  " + view.getX());
        animator.setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                animator.alpha(1f).xBy(100).scaleY(2f).translationY(100).setDuration(3000).setInterpolator(new CycleInterpolator(5)).start();
                Log.e("TAG", "animating...");
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });

        // 使用此方法   api>19
//        animator.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//            @Override
//            public void onAnimationUpdate(ValueAnimator animation) {
//
//            }
//        });
        animator.start();

    }

2.使用解析

1、獲取ViewPropertyAnimator對象

通過view.animate()方法獲取ViewPropertyAnimator對象animator

2、通過animator來改變一個view的屬性

animator.alpha(1f).xBy(100).scaleY(2f).translationY(100).setDuration(3000).setInterpolator(new CycleInterpolator(5));   

方法解析:

     * x(),y()方法分別改變view的x,y坐標到特定的值,絕對移動
     * xBy(offset),yBy(offset),view的x,y坐標的相對改變,相對值(offset),即相對當前移動多少,相對移動(alphaBy,translationXBy()等類似)
     * translationX(),translationY()改變的是view的translationX,translationY值,即偏移量
     * rotation() 旋轉view到特定的角度
     * scaleX(),scaleY() 縮放
     * setInterpolator() 設置插值器
     * withStartAction(Runnable runnable) 動畫開始動作   API level 16
     * withEndAction(Runnable runnable)   動畫結束動作,只有動畫正常結束時進行  API level 16

注:

    1、translationX表示的是view的x方向的偏移量(offset,左移為負,右移為正),x表示view的x坐標
    2、沒有調用start()方法,動畫依然可以運行,內部隱式啟動,自己也可調用start啟動

3、監聽動畫執行

- animator.setListener  設置動畫狀態監聽
    - onAnimationStart  當動畫開始
    - onAnimationEnd   當動畫結束
    - onAnimationCancel  當動畫取消
    - onAnimationRepeat 當動畫重復

- animator.setUpdateListener 設置更新監聽, 使用此方法   api>=19

4、Activity退出時停止動畫,防止內存洩漏

 @Override
    protected void onDestroy() {
        super.onDestroy();
        if (animator != null) {
            animator.cancel();
            animator = null;
        }
    }

ObjectAnimator 的使用

示例

/**
     * ObjectAnimator
     *
     * @param view
     */
    public void objectAnimator(final View view) {
        final ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1, 0.5f, 1);
        animator.addListener(new Animator.AnimatorListener() {   // 設置動畫監聽
            @Override
            public void onAnimationStart(Animator animation) {
                ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f, 1).setDuration(1000).start();
            }

            @Override
            public void onAnimationEnd(Animator animation) {

            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.setDuration(1000).start();

    }

使用解析

ObjectAnimator是ValueAnimator的繼承類,相比Animation動畫,它並不提供直接的四種動畫子類,而是以of方法來操作view的相關屬性,

常見of方法

- ofArgb(Object target, String propertyName, int... values)
- ofFloat(Object target, String propertyName, float... values)
- ofInt(Object target, String propertyName, int... values)
- ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
- ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)

offXXX方法分析

     target:指要操作的目標view或對象
     propertyName: 指屬性名,諸如alpha,scaleX,scaleY,rotationX,rotationY,translationX,translationY
     values: 指操作的屬性的值變化,比如ofFloat(targetView,"alpha",0,1);表示透明度從0到1
PropertyValuesHolder的使用
PropertyValuesHolder可以將設置的屬性變化效果臨時存儲起來,最後一起設置給view
 /**
     * PropertyValuesHolder的使用
     * @param view
     */
    public void propertyValuesHolder(View view) {

        final PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1, 0.5f, 1);
        final PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1, 0.5f, 1);
        final PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1, 0.5f, 1);
        final ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ivBall, alpha, scaleX, scaleY);
        animator.setDuration(1000).start();

    }

4.設置動畫監聽

- addListener   添加動畫監聽,可以監聽動畫的開始,取消,結束,重復
- addUpdateListener  添加更新監聽,
- addPauseListener   添加動畫暫停監聽

可以使用AnimatorListenerAdapter選擇性的監聽

animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
            }
        });

5.xml中的寫法


6.防止內存洩漏

    Activity退出時取消動畫,防止內存洩漏,調用cancel方法即可、  

7.使用原則

使用ObjectAnimator 要注意,1、被操作的view的屬性(property)要有set與get方法,2、同時set方法對view的操作能夠反映出來,否則操作失敗

8.對任意對象做動畫
針對以上使用原則若有一條不滿足則會使動畫無效,官方給出三種解決方案

1、如果你有權限的話,給你的對象添加set與get方法
2、用一個類來包裝原始對象,間接為其提供set與get方法
3、采用ViewAnimator,監聽動畫過程,自己實現屬性的改變

ValueAnimator 的使用的使用

ValueAnimator相對ObjectAnimator來說,可以不用操作任何對象,通常是操縱一個值的變化過程,監聽變化的過程,在其中做相應的屬性操作

使用示例

public void valueAnimator(final View view) {
        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(1000);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                final float fraction = animation.getAnimatedFraction();
                Log.e("TAG", "fraction=" + fraction);
                view.setTranslationY((float) (Math.sin(fraction*2*3.14159) * 200));
                view.setTranslationX((float) (Math.sin(fraction*2*3.14159) * 200));
            }
        });
    }

使用解析

1、常見ofXXX方法

ofArgb(int... values)
ofFloat(float... values)
ofInt(int... values)
ofPropertyValuesHolder(PropertyValuesHolder... values)
ofObject(TypeEvaluator evaluator, Object... values)

2、設置監聽(同ObjectAnimator)
3、xml中定義ValueAnimator




4、在java代碼中加載動畫

final Animator animator = AnimatorInflater.loadAnimator(AnimatorActivity.this,R.animator.animator_value);

5、還可以設置估值器與插值器

 valueAnimator.setEvaluator(new FloatEvaluator());
 valueAnimator.setInterpolator(new AccelerateInterpolator());

AnimatorSet的使用

使用示例

1.使用java代碼

    public void set(View view) {
        AnimatorSet set = new AnimatorSet();
        final ObjectAnimator scaleX = ObjectAnimator.ofFloat(ivBall, "scaleX", 1, 0.5f, 1);
        final ObjectAnimator scaleY = ObjectAnimator.ofFloat(ivBall, "scaleY", 1, 0.5f, 1);
        final ObjectAnimator translationX = ObjectAnimator.ofFloat(ivBall, "translationX", 0, 100, 0);
        final ObjectAnimator translationY = ObjectAnimator.ofFloat(ivBall, "translationY", 0, 100, 0);
        final ObjectAnimator rotationX = ObjectAnimator.ofFloat(ivBall, "rotationX", 0, 360);
        final ObjectAnimator rotationY = ObjectAnimator.ofFloat(ivBall, "rotationY", 0, 360);
        final ObjectAnimator alpha = ObjectAnimator.ofFloat(ivBall, "alpha", 1, 0.5f, 1);
//        set.playTogether(scaleX, scaleY, translationX, translationY, rotationX, rotationY, alpha);  //  一起
//        set.playSequentially(scaleX, scaleY, translationX, translationY, rotationX, rotationY, alpha); // 順序
        set.play(scaleX).with(scaleY).with(translationX).with(translationY).before(rotationX);
        set.play(rotationX).with(rotationY).after(alpha);  // 按指定順序

        set.setDuration(2000).start();
    }

2.在xml中定義動畫



    

在java代碼中使用定義的動畫

final Animator set = AnimatorInflater.loadAnimator(context,R.animator.animator_set);
        set.setTarget(target);
        set.start();

3、添加監聽 (同上,三種監聽方式)

使用解析

通過playTogether可以使動畫一起播放,playSequentially使動畫按次序播放,
通過play方法結合with、before、after可以明確指定播放次序,with指兩個動畫一起播放,before、after分別指一個動畫先/後於另一個動畫播放

插值器與估值器淺析

插值器(TimeInterpolator)

1、插值器的概念

    插值器定義了動畫變化的速率,通過不同的函數實現,來完成動畫的加速,減速,回彈,彈跳等效果。根據時間流逝的百分比來計算出當前屬性改變的百分比。

2、常見插值器

 OvershootInterpolator@android:anim/overshoot_interpolator快速到達終點並超出一小步最後回到終點
 AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator先加速再減速
 AccelerateInterpolator@android:anim/accelerate_interpolator加速
 AnticipateInterpolator@android:anim/anticipate_interpolator先回退一小步然後加速前進
 AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator在上一個基礎上超出終點一小步再回到終點
 DecelerateInterpolator@android:anim/decelerate_interpolator減速
 LinearInterpolator@android:anim/linear_interpolator勻速
 BounceInterpolator@android:anim/bounce_interpolator最後階段彈球效果
 CycleInterpolator@android:anim/cycle_interpolator周期運動

3、分析CycleInterpolator 源碼

由源碼可以看到插值器輸入的值與返回值關系表達式為:(float)(Math.sin(2 * mCycles * Math.PI * input)),當輸入一直增大時,輸出值在成sin曲線值來回交變,形成所需要的cycle效果

@HasNativeInterpolator
public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    public CycleInterpolator(float cycles) {
        mCycles = cycles;
    }

    public CycleInterpolator(Context context, AttributeSet attrs) {
        this(context.getResources(), context.getTheme(), attrs);
    }

    /** @hide */
    public CycleInterpolator(Resources resources, Theme theme, AttributeSet attrs) {

    }

    public float getInterpolation(float input) {
        return (float)(Math.sin(2 * mCycles * Math.PI * input));
    }

    private float mCycles;

}

4、自定義插值器
自定義Interpolator類實現Interpolator,並實現getInterpolation方法即可

簡單示例:

package com.yu.propertyanimator;

import android.annotation.TargetApi;
import android.os.Build;
import android.view.animation.Interpolator;

/**
 * Created by pecu on 2016/08/27.
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
public class MyInterpolator implements Interpolator {

    @Override
    public float getInterpolation(float input) {
        return (float) Math.abs(Math.sin(input * Math.PI));  // 折回效果
    }
}

估值器(TypeEvaluator)

通過插值器所獲的屬性改變百分比來估算當前的屬性值

1、 TypeEvaluator接口
先看TypeEvaluator接口,發現只有一個抽象方法evaluate,用於通過fraction來估算出當前值


package android.animation;

public interface TypeEvaluator {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * fraction representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: result = x0 + t * (x1 - x0),
     * where x0 is startValue, x1 is endValue,
     * and t is fraction.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         fraction parameter.

    public T evaluate(float fraction, T startValue, T endValue);

}

2、查看FloatEvaluator 源碼
可以發現,evaluate方法的返回值是通過這樣一個公式計算所得result = x0 + t * (x1 - x0);

package android.animation;

public class FloatEvaluator implements TypeEvaluator {

    /**
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type float or
     *                   Float
     * @param endValue   The end value; should be of type float or Float
     * @return A linear interpolation between the start and end values, given the
     *         fraction parameter.
     */

    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

3、自定義TypeEvaluator

自定義估值器較為簡單,只需要實現TypeEvaluator接口,並重寫evaluate方法即可

一個簡單自定義TypeEvaluator

package com.yu.propertyanimator;

import android.animation.TypeEvaluator;
import android.graphics.Point;

/**
 * Created by pecu on 2016/08/27.
 */
public class MyEvaluator implements TypeEvaluator {
    Point point;

    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        if (point == null) {
            point = new Point();
            point.x = (int) (startValue.x + fraction * (endValue.x - startValue.x));
            point.y = (int) (startValue.y + fraction * (endValue.y - startValue.y));
        } else {
            point.x = (int) (startValue.x + fraction * (endValue.x - startValue.x));
            point.y = (int) (startValue.y + fraction * (endValue.y - startValue.y));
        }
        return point;
    }
}

4、使用自定義的Evaluator

/**
     * 仿小球落地後回彈幾次
     * @param view
     */
    public void evaluate(View view) {
        final ValueAnimator valueAnimator = ValueAnimator.ofObject(new MyEvaluator(), new Point(0, 0), new Point(0, screenHeight - 2*ivBall.getHeight()));
        valueAnimator.setInterpolator(new BounceInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point point = (Point) animation.getAnimatedValue();
                ivBall.setX(point.x);
                ivBall.setY(point.y);
            }
        });
        valueAnimator.setDuration(1000);
        valueAnimator.start();

    }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved