安卓动画

package com.example.animationlearning1;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.drawable.AnimatedStateListDrawable;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    ImageView frameAnimIV1, frameAnimIV2, bjAnimIV3, bjAnimIV4, bjAnimIV5, bjAnimIV6, bjAnimIV7;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        frameAnimIV1 = (ImageView) findViewById(R.id.frame_anim_img1);
        frameAnimIV2 = (ImageView) findViewById(R.id.frame_anim_img2);
        bjAnimIV3 = (ImageView) findViewById(R.id.bj_anim_img3);
        bjAnimIV4 = (ImageView) findViewById(R.id.bj_anim_img4);
        bjAnimIV5 = (ImageView) findViewById(R.id.bj_anim_img5);
        bjAnimIV6 = (ImageView) findViewById(R.id.bj_anim_img6);
        bjAnimIV7 = (ImageView) findViewById(R.id.bj_anim_img7);
        /**帧动画:
         * 第一种方式是新建Animation对象,然后调用.addFrame()给该对象一帧一帧地传Drawable对象,并设置显示时长
         * 接着将AnimationDrawable对象传给Imageview对象。最后启动。
         * */
        AnimationDrawable animationDrawable1 = new AnimationDrawable();
        animationDrawable1.addFrame(this.getDrawable(R.drawable.item1),800);
        animationDrawable1.addFrame(this.getDrawable(R.drawable.item2),800);
        animationDrawable1.addFrame(this.getDrawable(R.drawable.item3),800);
        frameAnimIV1.setImageDrawable(animationDrawable1);
        animationDrawable1.start();

        /**
         * 第二种方式是将ImageView的background属性或者src属性设置为animation-list类型的xml文件。
         * 然后在活动中将其取出并转型为AnimationDrawable对象。然后启动或者关闭(stop())。
         * */
        AnimationDrawable animationDrawable2 = (AnimationDrawable)frameAnimIV2.getDrawable();
        animationDrawable2.start();


        /**
         * 补间动画: 设置动画在起止两个状态之间的动作的动画。包括透明度动画、位移动画、缩放动画、旋转动画
         * 以及这些动画的组合。
         * 补间动画的两种设置方式:
         * 第一种是新建动画对象然后设置属性值并用ImageView启动。
         * */

        // 透明度从0-1变化的动画
        Animation alphaAnimation = new AlphaAnimation(0,1); // 0全透明 1原图
        alphaAnimation.setDuration(1000);
        alphaAnimation.setInterpolator(new AccelerateInterpolator()); // 设置透明度切换速度的插值器。默认为线性插值器
        alphaAnimation.setRepeatCount(Animation.INFINITE);
        alphaAnimation.setRepeatMode(Animation.RESTART);
        bjAnimIV3.startAnimation(alphaAnimation);

        // 在Y方向位移自身长度
        Animation translateAnimation = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_SELF,0,Animation.RELATIVE_TO_SELF,0,
                                                            TranslateAnimation.RELATIVE_TO_SELF,0,TranslateAnimation.RELATIVE_TO_SELF,1);
        translateAnimation.setDuration(1000);
        translateAnimation.setInterpolator(new DecelerateInterpolator());
        translateAnimation.setRepeatCount(Animation.INFINITE);
        translateAnimation.setRepeatMode(Animation.RESTART);
        bjAnimIV4.startAnimation(translateAnimation);

        // 在xy方向上从0放大为自身长度
        Animation scalaAnimation = new ScaleAnimation(0,1,0,1);
        scalaAnimation.setDuration(1000);
        scalaAnimation.setInterpolator(new LinearInterpolator());
        scalaAnimation.setRepeatCount(Animation.INFINITE);
        scalaAnimation.setRepeatMode(Animation.RESTART);
        bjAnimIV5.startAnimation(scalaAnimation);

        // 以自身中点为中心旋转360°
        Animation rotateAnimation = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,50%,Animation.RELATIVE_TO_SELF,50%); // 0.5f和50%的区别是?
rotateAnimation.setDuration(1000); rotateAnimation.setInterpolator(new LinearInterpolator()); rotateAnimation.setRepeatCount(Animation.INFINITE); rotateAnimation.setRepeatMode(Animation.RESTART); bjAnimIV6.startAnimation(rotateAnimation); // 动画集,添加了透明度动画和旋转动画 AnimationSet animationSet = new AnimationSet(false); // true表示该动画集合内所有动画共享同一个插值器  animationSet.addAnimation(alphaAnimation); animationSet.addAnimation(rotateAnimation); bjAnimIV7.startAnimation(animationSet); /*** * 第二种是新建xml文件方式 然后用AnimationUtils.load()方法加载成Animation对象,用ImageView启动。 */ } }

 

3. 属性动画

3.1 基础的属性动画 

3.1.1 通过ViewPropertyAnimator对象为View对象设置属性动画

textView = findViewById(R.id.text);
         //通过View对象的.animate()方法获取ViewPropertyAnimator对象
        ViewPropertyAnimator viewPropertyAnimator = textView.animate();
        //设置缩放、持续时间、位移、插值器等属性
        viewPropertyAnimator.scaleX(1f).setDuration(1000).setInterpolator(new LinearInterpolator());
        viewPropertyAnimator.x(1f);
        viewPropertyAnimator.rotation(100f);
        viewPropertyAnimator.rotationBy(360f); // 带-By后缀的方法表示将该属性增加xxx
        viewPropertyAnimator.alpha(0.5f);

3.1.2 通过ObjectAnimator对象为View对象设置属性动画

该方式主要针对自定义View的动画实现。

//1. 自定义View并设置自定义属性的get和set方法
public class MyView extends androidx.appcompat.widget.AppCompatImageView {
    private float attr;
    public MyView(Context context) {
        super(context);
    }
    
    public void setMyProperty(float attr){
        
        this.attr = attr;
        /*
        执行业务逻辑....
        */
        invalidate(); // 重绘,将调用draw()进行画面重绘
        
    }
    
    public double getMyProperty(){
        return this.attr;
    }
}

 

//2. 为属性设置值,然后获取ObjectAnimator并启动 [values: 起始值(如果没有起始值属性就必须有get方法) 0个或多个转接点值 目标值]
         ObjectAnimator ojAnimator = ObjectAnimator.ofFloat(myTextView,"MyProperty",0f,1f);
         ojAnimator.start();

 

3.1.3 TypeEvaluator和动画同时播放以及按照次序播放

public class MainActivity extends AppCompatActivity {

    private static final String tag = "AnimationTAG";
    private ImageView img;
    private Button evaBtn, OJABtn,ASBtn1,ASBtn2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img = (ImageView) findViewById(R.id.img);
        evaBtn = (Button) findViewById(R.id.typeevaluator);
        OJABtn = (Button) findViewById(R.id.property_value_holder);
        ASBtn1 = (Button) findViewById(R.id.object_animator_animationset_parall);
        ASBtn2 = (Button) findViewById(R.id.object_animator_animationset_serial);


        evaBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ObjectAnimator animator1 = ObjectAnimator.ofFloat(img,"scaleX",0f,1f);
                        //自定义补间器,指定缩放系数在0-1之间的变化
                        animator1.setEvaluator(new MyEvaluator());
                animator1.setDuration(2000);
                animator1.start();

            }
        });

        OJABtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 使用PropertyValuesHolder作为动画属性存放器,然后用ObjectAnimator对象播放。达成的效果是几种动画效果
                 * 同时播放,持续时间一样并公用插值器。
                 * */
                PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("scaleX",0f,1f);
                PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("alpha",0f,1f);
                PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("rotation",0f,360f);
                ObjectAnimator animator2 = ObjectAnimator.ofPropertyValuesHolder(img,pvh1,pvh2,pvh3);
                animator2.setDuration(2000);
                animator2.start();
            }
        });

        ASBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 使用ObjectAnimator + AnimatorSet实现多个动画效果同时播放
                 * */
                ObjectAnimator animator3 = ObjectAnimator.ofFloat(img,"scaleX",0f,1f);
                ObjectAnimator animator4 = ObjectAnimator.ofFloat(img,"X",0f,200f);
                AnimatorSet animatorSet = new AnimatorSet();
                animatorSet.playTogether(animator3,animator4);
                animatorSet.setDuration(2000);
                animatorSet.start();
            }
        });

        ASBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 使用ObjectAnimator + AnimatorSet实现多个动画效果按照指定顺序播放(before,after)
                 * */
                ObjectAnimator animator3 = ObjectAnimator.ofFloat(img,"scaleX",0f,1f);
                ObjectAnimator animator4 = ObjectAnimator.ofFloat(img,"X",0f,200f);
                AnimatorSet animatorSet = new AnimatorSet();
                animatorSet.play(animator3).after(animator4);
                animatorSet.setDuration(2000);
                animatorSet.start();
            }
        });

    }

    class MyEvaluator implements TypeEvaluator<Float>{

        @Override
        public Float evaluate(float fraction, Float startValue, Float endValue) {
            // fraction自动从0-1
            return startValue + fraction * fraction;
        }
    }

}

 3.1.4 指定关键帧

keyFramesBtn.setOnClickListener(new View.OnClickListener() {
            /**
             * 通过多个Keyframe对象为PropertyValuesHolder指定更精确的属性动画效果。
             * 第一个Keyframe的第一个值和最后一个Keyframe的第二个值将分别作为起始值和最终值。
             * 当属性值为Keyframe的第一个值时,将迅速调整为第二个值。
             * */
            @Override
            public void onClick(View v) {
                Keyframe keyframe1 = Keyframe.ofFloat(0,0);
                Keyframe keyframe2 = Keyframe.ofFloat(0.5f,0.9f);
                Keyframe keyframe3 = Keyframe.ofFloat(0.9f,.5f);
                PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("alpha",keyframe1,keyframe2,keyframe3);
                ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(img,propertyValuesHolder);
                objectAnimator.setDuration(5000);
                objectAnimator.start();

            }
        });

 

posted @ 2021-08-31 10:49  日进一卒  阅读(64)  评论(0)    收藏  举报