Android 利用屬ObjectAnimator,AnimatorSet性動畫繪制一個彈球,加速下落,到底部時擠壓,然后減速上彈


屬性動畫主要的幾個類介紹:

1.ValueAnimator:這個類提供了一個簡單的計時引擎運行動畫動畫計算值和設置目標對象。注意:使用該類時一般都是用:ObjectAnimator,而基於ObjectAnimator執行的屬性動畫,都是根據java的反射機制來設置的,因此設置動畫的目標對象的屬性必須有getter 和setter方法。

  setDuration:設置動畫的時間

  setInterpolator:設置一個插入器,例如:減速器(DecelerateInterpolator),加速器(AccelerateInterpolator),當然也可以自定義,自定義時只需要繼承這兩個類就行了,這里就不做討論了。

  setEvaluator:設置評估者

    1.ArgbEvaluator:這種評估者可以用來執行類型之間的插值整數值代表ARGB顏色。

    2.FloatEvaluator:這種評估者可以用來執行浮點值之間的插值。
    3.IntEvaluator:這種評估者可以用來執行類型int值之間的插值。
    4.RectEvaluator:這種評估者可以用來執行類型之間的插值矩形值。

  setRepeatCount:設置動畫的重復次數(是一個int類型的值)

  setRepeatMode:設置動畫模式

  start:啟動動畫

2.AnimatorSet:這個類為一組特定的動畫指定順序。

  總要方法如下:

  play:該方法創建一個構造器對象用於創建約束。

  playTogether:設置同時運行一組動畫

  pase:暫停一個正在運行的動畫

  resume:重新運行暫停后的動畫

  isRunning:判斷動畫是否正在運行

  isStarted:判斷動畫是否已經運行了

  start:開始動畫

3.AnimatorSet.Builder創建一個用於約束動畫的建造器

  after(Animator):執行前面的動畫后執行該動畫

  after(long delay):延遲n毫秒之后執行動畫

  before(Animator):執行前面動畫前執行動畫

  with(Animator):和前面動畫一塊執行

4.ShapeDrawable:模型drawable,創建時需要傳入一個圖形模型

 

以下是一個簡單的Demo例子用於測試以上情況(小球加速下落擠壓后減速上彈)

一、BackgroundView.java

package cn.yw.lib.animation;

import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;

/**
 * 屬性動畫,背景輪詢切換
 * 為什么要使用SurfaceView而不是用View:
 *     1.這里稍作解釋,由於SurfaceView繼承了View,繪制起來和SurfaceView沒有太大的區別,
 *  2.SurfaceView本身自帶雙緩沖技術,能夠更好的支持動畫操作
 * 
 * 
 * @author yw-tony
 * 
 */
@SuppressLint("NewApi")
public class BackgroundView extends SurfaceView implements
        SurfaceHolder.Callback, Runnable {
    
    private SurfaceHolder holder;
    private ShapeHolder shapHolder;

    public BackgroundView(Context context) {
        super(context);
        this.holder = this.getHolder();
        this.holder.addCallback(this);
    }

    /**
     * 創建一個小球
     */
    private void createABall(float x, float y) {
        OvalShape oval = new OvalShape();
        //設置拓原模型的寬高都為50f,即模型為原型
        oval.resize(50f, 50f);
        //創建一個模型drawable
        ShapeDrawable drawable = new ShapeDrawable(oval);
        shapHolder = new ShapeHolder(drawable);
        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);
        int color = 0xff000000 | red << 16 | green << 8 | blue;
        Paint paint = drawable.getPaint(); // new Paint(Paint.ANTI_ALIAS_FLAG);
        int darkColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue / 4;
        RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f, color,
                darkColor, Shader.TileMode.CLAMP);
        //設置畫筆顏色
        paint.setShader(gradient);
        shapHolder.setPaint(paint);
        //設置小球的初始位置
        shapHolder.setX(x);
        shapHolder.setY(y);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() != MotionEvent.ACTION_DOWN
                && event.getAction() != MotionEvent.ACTION_MOVE) {
            return false;
        }
        //創建一個小球
        createABall(event.getX(), event.getY());
        //設置動畫的Y軸活動范圍
        float startY = shapHolder.getY();
        float endY = getHeight() - 50f;
        // int duration = (int)(500 * ((h - eventY)/h));
        // 小球彈跳動畫的時間為500毫秒
        int duration = 500;
        ValueAnimator bounceAnim = ObjectAnimator.ofFloat(shapHolder, "y",
                startY, endY);
        bounceAnim.setDuration(duration);
        // 加速器,小球會加速下落
        bounceAnim.setInterpolator(new AccelerateInterpolator());
        // 以下幾個是擠壓動畫
        
        ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(shapHolder, "x",
                ////設置x周的動畫范圍
                shapHolder.getX(), shapHolder.getX() - 25f);
        //設置壓縮動畫時間為下落動畫時間的四分之一
        squashAnim1.setDuration(duration / 4);
        squashAnim1.setRepeatCount(1);
        squashAnim1.setRepeatMode(ValueAnimator.REVERSE);
        //擠壓是做減速運動
        squashAnim1.setInterpolator(new DecelerateInterpolator());
        ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(shapHolder, "width",
                //設置小球寬度動畫
                shapHolder.getWidth(), shapHolder.getWidth() + 50);
        squashAnim2.setDuration(duration / 4);
        squashAnim2.setRepeatCount(1);
        squashAnim2.setRepeatMode(ValueAnimator.REVERSE);
        //小球做減速運動
        squashAnim2.setInterpolator(new DecelerateInterpolator());
        //設置伸展動畫
        ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(shapHolder, "y",
                endY, endY + 25f);
        stretchAnim1.setDuration(duration / 4);
        stretchAnim1.setRepeatCount(1);
        
        stretchAnim1.setInterpolator(new DecelerateInterpolator());
        stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);
        ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(shapHolder,
                "height", shapHolder.getHeight(), shapHolder.getHeight() - 25);
        stretchAnim2.setDuration(duration / 4);
        stretchAnim2.setRepeatCount(1);
        stretchAnim2.setInterpolator(new DecelerateInterpolator());
        stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);

        ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(shapHolder, "y",
                endY, startY);
        bounceBackAnim.setDuration(duration);
        // 減速器
        bounceBackAnim.setInterpolator(new DecelerateInterpolator());
        
        //設置動畫對象的順序
        AnimatorSet bouncer = new AnimatorSet();
        //先加速下落然后再執行擠壓動畫1
        bouncer.play(bounceAnim).before(squashAnim1);
        //播放擠壓動畫1的同事播放擠壓動畫2
        bouncer.play(squashAnim1).with(squashAnim2);
        bouncer.play(squashAnim1).with(stretchAnim1);
        bouncer.play(squashAnim1).with(stretchAnim2);
        //執行完擠壓動畫后執行小球彈起動畫
        bouncer.play(bounceBackAnim).after(stretchAnim2);
        //開始執行動畫
        bouncer.start();
        return true;
    }

    private void drawBall() {
        Canvas canvas = null;
        try {
            canvas = holder.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(Color.GRAY);
                canvas.save();
                //如果小球為空則不執行繪制動作
                if (shapHolder != null) {
                    canvas.translate(shapHolder.getX(), shapHolder.getY());
                    shapHolder.getShape().draw(canvas);
                }
                canvas.restore();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //解鎖畫布
                if (holder != null) {
                    holder.unlockCanvasAndPost(canvas);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //開啟繪制線程
        new Thread(this).start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public void run() {
        try {
            //此處為死循環,大家在寫的時候可以加上一個boolean變量值,當用戶點擊回退鍵(back)時,結束線程
            while (true) {
                drawBall();
                Thread.sleep(200);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

二、BackgroundViewActivity.java

package cn.yw.lib.animation;

import android.app.Activity;
import android.os.Bundle;

public class BackgroundViewActivity extends Activity{
    private BackgroundView view;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        view = new BackgroundView(this);
        setContentView(view);
    }

}

 

 

 

  

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM