• <Android 基础(三十一)> ObjectAnimator


    简介

    ObjectAnimator,是ValueAnimator的子类,支持利用目标视图的属性来实现动画效果。构造ObjectAnimator的时候,将会提取对应的参数来定义动画对象和对象属性。合适的get/set方法是视图实现属性动画的内部机理,动画过程中,系统将通过get/set方法来实现效果,也就是根据一定的规律来为View设置属性。
    Animators可以用过资源文件或者是代码定义,当使用资源文件创建的时候,若使用PropertyValuesHolder和Keyframe可以创建出更加复杂的动画,使用PropertyValuesHolder可以实现几个属性的并行变化。
    使用Keyframes,可以实现更复杂的动画过程中的属性变化方式。我们可以为每一个Keyframes明确一个fractional value(因子,0-1)来决定在整个动画过程中什么时候到达这个属性值。不设置fractions的时候,这些关键帧将会均匀的分布在整个动画过程中。至于那些没有指定value值的关键帧,将会在动画开始的时候推导出他们的 value。初次之外,我们可以给关键帧添加插值器,整个插值器将会在被设置的这一帧和前一帧动画之间。对于没有设置插值器的关键帧,将会给他们提供一个默认的插值器AccelerateDecelerateInterpolator

    XML实现

    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:repeatCount="1"
        android:repeatMode="reverse">
        <!-- BEGIN_INCLUDE(KeyframeResources) -->
        <propertyValuesHolder android:propertyName="x">
            <keyframe
                android:fraction="0"
                android:value="800" />
            <keyframe
                android:fraction=".2"
                android:interpolator="@android:anim/accelerate_interpolator"
                android:value="1000" />
            <keyframe
                android:fraction="1"
                android:interpolator="@android:anim/accelerate_interpolator"
                android:value="400" />
        </propertyValuesHolder>
        <propertyValuesHolder android:propertyName="y">
            <keyframe />
            <keyframe
                android:fraction=".2"
                android:interpolator="@android:anim/accelerate_interpolator"
                android:value="300" />
            <keyframe
                android:interpolator="@android:anim/accelerate_interpolator"
                android:value="1000" />
        </propertyValuesHolder>
        <!-- END_INCLUDE(KeyframeResources) -->
    </objectAnimator>
    objectAnimator属性值 含义
    android:propertyName 属性名称
    android:valueTo 动画结束时属性的值
    android:valueFrom 动画开始时属性的值
    android:duration 动画时长
    android:startOffset 动画延迟几秒播放,调用start()方法后延迟
    android:repeatCount 动画重复次数
    android:repeatMode 动画重复的方式,restart/reverse
    android:valueType 属性值类型,intType,floatType,colorType,pathType


    propertyValuesHolder属性值和objectAnimator基本相同

    keyframe属性值 含义
    android:fraction 插值因子
    android:interpolator 插值器,用在当前帧和前一帧之间
    android:value 需要设置的属性值

    代码实现

    public class MainActivity extends AppCompatActivity {
    
        private int width;
        private int height;
        private ImageView imageView = null;
        private ImageView loveImageView = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            toolbar.setNavigationIcon(R.drawable.left);
            setSupportActionBar(toolbar);//设置ActionBar
    
            getWidthAndHeight();//获取屏幕大小
            imageView = (ImageView) findViewById(R.id.ball);
            loveImageView = (ImageView) findViewById(R.id.love);
        }
    
        /*
          心跳
         */
        public void doAnimation(final View view) {
            PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
                    0.8f, 1f, 0.8f, 1.0f);
            PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 0.6f,
                    0.8f, 1f, 0.8f, 1.0f);
            PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 0.6f,
                    0.8f, 1f, 0.8f, 1.0f);
            ObjectAnimator.ofPropertyValuesHolder(loveImageView, pvhX, pvhY, pvhZ).setDuration(1000).start();//创建属性动画并开始
        }
    
    
        /*
        抛物线
         */
        public void doGtAnimation(final View view) {
            ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "yidong", 0, 1, 0).setDuration(3000);
            /*设置动画更新监听器,通过手动设置属性来实现view属性的改变达到动画的效果*/
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float cVal = (Float) animation.getAnimatedValue();
                    imageView.setX(5 * cVal * 100);
                    imageView.setY(5 * cVal * 3 * cVal * 3 * 100);
                }
            });
            /*设置动画过程监听器,监听开始结束取消等动作*/
            anim.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    System.err.println("yidong -- onAnimationStart");
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    System.err.println("yidong -- onAnimationEnd");
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
                    System.err.println("yidong -- onAnimationCancel");
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
                    System.err.println("yidong -- onAnimationRepeat");
                }
            });
            /*重复魔石*/
            anim.setRepeatMode(ValueAnimator.RESTART);
            /*重复次数*/
            anim.setRepeatCount(2);
            anim.start();
    
        }
    
        /*
        转圈圈
         */
        public void doCircleAnimation(View view) {
            ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "yidong", 0, 2 * (float) Math.PI).setDuration(1000);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    System.err.println("yidong -- value = " + animation.getAnimatedValue());
                    float cVal = (Float) animation.getAnimatedValue();
                    imageView.setX((float) Math.sin(cVal) * 200 + width / 2);
                    imageView.setY((float) Math.cos(cVal) * 200 + height / 2);
                }
            });
            anim.setRepeatMode(ValueAnimator.REVERSE);
            anim.setRepeatCount(-1);//无限重复
            anim.start();
        }
    
        /*
        从xml文件中提取动画
         */
        public void doXmlAnimation(View view) {
            Animator animator = AnimatorInflater.loadAnimator(this, R.animator.one);//从xml文件中添加动画
            animator.setTarget(loveImageView);
            animator.start();
        }
    
        /*
        获取屏幕的宽高
         */
        private void getWidthAndHeight() {
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            width = dm.widthPixels;
            height = dm.heightPixels;
            System.err.println("yidong -- width = " + width);
            System.err.println("yidong -- height = " + height);
        }
    }

    实际效果

    这里写图片描述


    这里写图片描述

    写在最后

    属性动画的内容很丰富,这里只是提到了ObjectAnimator的一些简单实现,很深入和全面的东西,需要自己看源码,熟悉对应的API

  • 相关阅读:
    python3 pyinstaller
    python3 random
    python3 turtle
    产生一个序列的所有排列组合
    蒙特卡洛算法
    lightoj 1014
    UVA11426
    nginx 配置本地https(免费证书)
    ElementUI
    Airbnb 代码规范
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467156.html
Copyright © 2020-2023  润新知