【学习笔记】Android属性动画学习


由于Android3.0之前已有的动画框架Animation存在依稀局限性---动画改变的只是显示,并不能响应事件。 因此3.0之后Google就提出了属性动画这样一个新的动画框架,帮助开发者实现更加丰富的动画效果。

属性动画中最基本的ObjectAnimator.

在Animator框架中使用最多的就是AnimatorSet和ObjectAnimator配合。

使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值。

而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。而且ObjectAnimator能够自动驱动,可以调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,

调整帧率,减少动画过程中频繁绘制界面,而在不影响动画效果的前提下减少CPU资源消耗。最重要的是,属性动画通过调用属性的get、set方法来真实地控制了一个View的属性值,

因此强大的属性动画框架,基本可以实现所有的动画效果。

平移动画代码:


int count = 0;
btn_objectanimation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int step =  count*10+10;
                ObjectAnimator oa = ObjectAnimator.ofFloat(
                        btn_objectanimation,
                        "translationX",
                        step
                );
                oa.setDuration(1000);
                oa.start();
                count++;
            }
        });


在使用ObjectAnimator的时候,有一点非常重要,那就是要操作的属性必须具有get、set方法,不然ObjectAnimator就无法起效。

下面就是一些常用的可以直接使用属性动画的属性值:


  • translationX 和 translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标偏移的位置。

  • rotation、roataionX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转。

  • scaleX和scaleY:这两个属性控制着View对象围绕它的支点进行2D缩放

  • pivotX和pivotY:这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点。

  • x和y,这是两个简单实用的属性,它描述了View对象在它的容器中的最终位置,它是最初的左上角坐标和translationX、translationY值的累计和。

  • alpha:它表示View对象的alpha透明度。默认值是1 (不透明),0代表完全透明(不可见)

如果一个属性没有get、set方法,可以通过自定义一个属性类或者包装类,来间接地给这个属性增加get、set方法,或者通过ValueAnimator来实现。

通过自定义属性类代码如下:


private static class WrapperView{
        private View mTarget;

        public WrapperView(View target){
            this.mTarget = target;
        }

        public int getWidth(){
            return mTarget.getLayoutParams().width;
        }

        public void setWidth(int width){
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }
    }

使用时只需要操纵包装类就可以间接调用到get、set方法了:


WrapperView wrapperView = new WrapperView(btn_objectanimation);
                ObjectAnimator.ofInt(wrapperView, "width", 500).setDuration(5000).start();



效果如下:


PropertyValuesHolder

类似视图动画中的AnimationSet,在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画,可以使用PropertyValuesHolder来实现。

例子:平移动画+改变x、y轴的缩放:


 PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);
                PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
                PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
                ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(1000).start();



效果如图:



同时可以使用AnimatorSet完成上面多个动画效果:

代码:

 ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
                ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0, 1f);
                ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0, 1f);
                AnimatorSet set = new AnimatorSet();
                set.setDuration(1000);
                set.playTogether(animator1, animator2, animator3);
                set.start();

在AnimatorSet中,正是通过playTogether()、playSequentially()、animSet.play().with()、before()、after()这些方法来控制多个动画的协同工作方式,从而做到对动画播放顺序的精确控制。


ValueAnimator

ValueAnimator在属性动画中占有非常重要的地位,虽然不像ObjectAnimator那样耀眼,但它却是属性动画的核心所在,ObjectAnimator也是集成自ValueAnimator.


public final class ObjectAnimator extends ValueAnimator



ValueAnimator本身不提供任何动画效果,它更像一个数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程,

ValueAnimator的一般使用方法如下所示,通常情况下,在ValueAnimator的AnimatorUpdateListener中监听数值的变换,从而完成动画的变换。


 ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
                animator.setTarget(view);
                animator.setDuration(1000).start();
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
                        Float value = (Float)valueAnimator.getAnimatedValue();
                        Log.e("value", value+"");

                        TranslateAnimation ta = new TranslateAnimation(0, value, 0, 0);
                        ta.setDuration(1000);
                        btn_objectanimation.startAnimation(ta);
                    }
                });



日志如下:
02-17 13:10:02.240 13420-13420/com.jiarong.animationdemo E/value: 0.0
02-17 13:10:02.256 13420-13420/com.jiarong.animationdemo E/value: 0.06315112
02-17 13:10:02.276 13420-13420/com.jiarong.animationdemo E/value: 0.26845932
02-17 13:10:02.292 13420-13420/com.jiarong.animationdemo E/value: 0.61558187
02-17 13:10:02.308 13420-13420/com.jiarong.animationdemo E/value: 1.0709554
02-17 13:10:02.324 13420-13420/com.jiarong.animationdemo E/value: 1.6901821
02-17 13:10:02.340 13420-13420/com.jiarong.animationdemo E/value: 2.447176
02-17 13:10:02.356 13420-13420/com.jiarong.animationdemo E/value: 3.2835484
02-17 13:10:02.372 13420-13420/com.jiarong.animationdemo E/value: 4.3014555
02-17 13:10:02.392 13420-13420/com.jiarong.animationdemo E/value: 5.4496737
02-17 13:10:02.408 13420-13420/com.jiarong.animationdemo E/value: 6.6464663
02-17 13:10:02.420 13420-13420/com.jiarong.animationdemo E/value: 8.037975
02-17 13:10:02.440 13420-13420/com.jiarong.animationdemo E/value: 9.549156
02-17 13:10:02.456 13420-13420/com.jiarong.animationdemo E/value: 11.076882
02-17 13:10:02.476 13420-13420/com.jiarong.animationdemo E/value: 12.807748
02-17 13:10:02.488 13420-13420/com.jiarong.animationdemo E/value: 14.644662
02-17 13:10:02.504 13420-13420/com.jiarong.animationdemo E/value: 16.465723
02-17 13:10:02.520 13420-13420/com.jiarong.animationdemo E/value: 18.493307
02-17 13:10:02.540 13420-13420/com.jiarong.animationdemo E/value: 20.610731
02-17 13:10:02.556 13420-13420/com.jiarong.animationdemo E/value: 22.680279
02-17 13:10:02.572 13420-13420/com.jiarong.animationdemo E/value: 24.954662
02-17 13:10:02.588 13420-13420/com.jiarong.animationdemo E/value: 27.300476
02-17 13:10:02.608 13420-13420/com.jiarong.animationdemo E/value: 29.567537
02-17 13:10:02.624 13420-13420/com.jiarong.animationdemo E/value: 32.032734
02-17 13:10:02.640 13420-13420/com.jiarong.animationdemo E/value: 34.54915
02-17 13:10:02.660 13420-13420/com.jiarong.animationdemo E/value: 36.957924
02-17 13:10:02.676 13420-13420/com.jiarong.animationdemo E/value: 39.5532
02-17 13:10:02.688 13420-13420/com.jiarong.animationdemo E/value: 42.178284
02-17 13:10:02.708 13420-13420/com.jiarong.animationdemo E/value: 44.669437
02-17 13:10:02.724 13420-13420/com.jiarong.animationdemo E/value: 47.33092
02-17 13:10:02.740 13420-13420/com.jiarong.animationdemo E/value: 50.0
02-17 13:10:02.756 13420-13420/com.jiarong.animationdemo E/value: 52.512222
02-17 13:10:02.776 13420-13420/com.jiarong.animationdemo E/value: 55.174343
02-17 13:10:02.792 13420-13420/com.jiarong.animationdemo E/value: 57.821716
02-17 13:10:02.808 13420-13420/com.jiarong.animationdemo E/value: 60.293125
02-17 13:10:02.824 13420-13420/com.jiarong.animationdemo E/value: 62.89036
02-17 13:10:02.840 13420-13420/com.jiarong.animationdemo E/value: 65.45085
02-17 13:10:02.856 13420-13420/com.jiarong.animationdemo E/value: 67.82059
02-17 13:10:02.876 13420-13420/com.jiarong.animationdemo E/value: 70.288994
02-17 13:10:02.892 13420-13420/com.jiarong.animationdemo E/value: 72.699524
02-17 13:10:02.908 13420-13420/com.jiarong.animationdemo E/value: 74.909256
02-17 13:10:02.924 13420-13420/com.jiarong.animationdemo E/value: 77.18804
02-17 13:10:02.940 13420-13420/com.jiarong.animationdemo E/value: 79.38927
02-17 13:10:02.956 13420-13420/com.jiarong.animationdemo E/value: 81.384575
02-17 13:10:02.976 13420-13420/com.jiarong.animationdemo E/value: 83.4176
02-17 13:10:02.992 13420-13420/com.jiarong.animationdemo E/value: 85.35534
02-17 13:10:03.008 13420-13420/com.jiarong.animationdemo E/value: 87.0871
02-17 13:10:03.020 13420-13420/com.jiarong.animationdemo E/value: 88.824326
02-17 13:10:03.036 13420-13420/com.jiarong.animationdemo E/value: 90.45084
02-17 13:10:03.056 13420-13420/com.jiarong.animationdemo E/value: 91.876396
02-17 13:10:03.076 13420-13420/com.jiarong.animationdemo E/value: 93.275055
02-17 13:10:03.092 13420-13420/com.jiarong.animationdemo E/value: 94.55032
02-17 13:10:03.104 13420-13420/com.jiarong.animationdemo E/value: 95.63458
02-17 13:10:03.124 13420-13420/com.jiarong.animationdemo E/value: 96.66023
02-17 13:10:03.140 13420-13420/com.jiarong.animationdemo E/value: 97.552826
02-17 13:10:03.156 13420-13420/com.jiarong.animationdemo E/value: 98.26908
02-17 13:10:03.176 13420-13420/com.jiarong.animationdemo E/value: 98.89647
02-17 13:10:03.188 13420-13420/com.jiarong.animationdemo E/value: 99.384415
02-17 13:10:03.208 13420-13420/com.jiarong.animationdemo E/value: 99.71504
02-17 13:10:03.224 13420-13420/com.jiarong.animationdemo E/value: 99.92871
02-17 13:10:03.240 13420-13420/com.jiarong.animationdemo E/value: 100.0


动画事件的监听

一个完整的动画具有Start、Repeat、End、Cancel四个过程,通过Android提供的接口,可以很方便地监听到这四个事件,代码如下所示:


ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
                anim.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animator) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animator) {

                    }

                    @Override
                    public void onAnimationCancel(Animator animator) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animator) {

                    }
                });
                anim.start();


大部分时候,我们都只关心onAnimationEnd事件,所以Android也提供了一个AnimatorListenerAdapter来让我们选择必要的事件进行监听,代码如下:


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



可以选择实现你想要的事件:

【学习笔记】Android属性动画学习_第1张图片


属性动画写在XML中,

代码如下所示:注意该文件位置如图所示:你没看错,是在animator资源文件夹下

【学习笔记】Android属性动画学习_第2张图片

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType">

</objectAnimator>



使用方法:


  Animator anim = AnimatorInflater.loadAnimator(MainActivity.this, R.animator.scalex);
                anim.setTarget(view);
                anim.start();


View的animate方法

在Android3.0之后,Google给View增加了animate方法来直接驱动属性动画,代码如下所示:

可以发现,其实animate方法可以认为是属性动画的一种简写方式:


view.animate().alpha(0).y(300).setDuration(300).withStartAction(new Runnable() {
                    @Override
                    public void run() {

                    }
                }).withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {

                            }
                        });
                    }
                }).start();



模拟电视机关闭的效果,让一个图片纵向比例不断缩小


public class CustomTV extends Animation {

    private int mCenterWidth;
    private int mCenterHeight;
    private Camera camera;
    private float mRotateY = 0.0f;

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        //设置默认时长
        setDuration(2000);
        //动画结束后保留状态
        setFillAfter(true);
        //设置默认插值器
        setInterpolator(new BounceInterpolator());
        mCenterWidth = width / 2;
        mCenterHeight = height / 2;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final Matrix matrix = t.getMatrix();
        matrix.preScale(1, 1 - interpolatedTime, mCenterWidth, mCenterHeight);
    }
}



使用:


//电视机缩放动画
        ImageView mImageView = (ImageView)findViewById(R.id.mImageView);
        mImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CustomTV customTV = new CustomTV();
                view.startAnimation(customTV);
            }
        });



效果:

【学习笔记】Android属性动画学习_第3张图片


自定义动画:

public class CustomAnimation extends Animation {
    private int mCenterWidth;
    private int mCenterHeight;
    private Camera mCamera = new Camera();
    private float mRotateY = 0.0f;

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        // 设置默认时长
        setDuration(2000);
        // 动画结束后保留状态
        setFillAfter(true);
        // 设置默认插值器
        setInterpolator(new BounceInterpolator());
        mCenterWidth = width / 2;
        mCenterHeight = height / 2;
    }

    //设置旋转角度
    public void setRotateY(float rotateY){
        mRotateY = rotateY;
    }

    /**
     *
     * @param interpolatedTime 插值器的时间因子,这个因子由当前动画当前完成的百分比 和 当前时间所对应的插值所计算得来,取值范围为0到1.0
     * @param t 矩阵的封装类,一般使用这个类来获得当前的矩阵对象
     */
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final Matrix matrix = t.getMatrix();
        mCamera.save();
        //使用Camera设置旋转的角度
        mCamera.rotateY(mRotateY * interpolatedTime);
        //将旋转变换作用到matrix上
        mCamera.getMatrix(matrix);
        mCamera.restore();
        //通过pre方法设置矩阵作用前的偏移量来改变旋转中心
        matrix.preTranslate(mCenterWidth, mCenterHeight);
        matrix.postTranslate(-mCenterWidth, -mCenterHeight);
    }
}



使用:

ImageView mImageViewRotate = (ImageView)findViewById(R.id.mImageViewRotate);
        mImageViewRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               CustomAnimation customAnimation = new CustomAnimation();
                customAnimation.setRotateY(30);
                view.startAnimation(customAnimation);
            }
        });



效果:

【学习笔记】Android属性动画学习_第4张图片

你可能感兴趣的:(【学习笔记】Android属性动画学习)