Android动画

作者: 咸鱼佬 | 来源:发表于2017-05-11 11:17 被阅读133次

    Android 动画大致可以分为view animation(视图动画,补间动画) ,drawable animation(帧动画),property animation(属性动画)

    View Animation

    视图动画只能作用于view对象,是对view的变换,有以下的四种变换

    1. AlphaAnimation(透明度变化)
    2. ScaleAnimation(缩放变化)
    3. TranslateAnimation(位移变化)
    4. RotateAnimation (旋转变化)

    还有一个AnimationSet让上面的动画集合起来一起运行,都是Animation的子类

    AlphaAnimation

    直接alpha作为根元素

    <?xml version="1.0" encoding="utf-8"?>
    <alpha
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:fillAfter="true"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        >
    </alpha>
    

    或者用set作为根元素

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <alpha
            android:duration="2000"
            android:fillAfter="true"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"
            />
    </set>
    

    将xml加载到view中

    alphaImageView.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.alpha));
    

    再或者可以直接用java new 一个AlphaAnimation出来

    AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
    alphaAnimation.setDuration(1000);//必须设置一个大于0的数值,默认是0
    alphaImageView.startAnimation(alphaAnimation);
    

    运行的gif就不放了,用到的属性说明下,

    • toAlpha 动画结束时的透明度 float (0.0 ~ 1.0,完全透明~完全不透明)
    • fromAlpha 动画开始的透明度 float
    • duration 动画持续时间 单位毫秒
    • fillAfter 动画结束后是否保持结束后的状态 boolean true为保持

    ScaleAnimation

    参数介绍 :

    • fromX 动画开始时X轴的缩放比例,1.0表示当前view的正常比例
    • toX 动画结束时x轴的缩放比例,那么在x轴缩放的比例就是 toX - fromX
    • fromY 类似
    • toY 类似
    • pivotX x方向上的缩放起点,默认是0
    • pivotY Y方向上的缩放起点,默认是0
    • pivotType 缩放起点的类型,有三种
        /**
         * The specified dimension is an absolute number of pixels.
         * 默认是这种,相对于控件的0坐标
         */
        public static final int ABSOLUTE = 0;
    
        /**
         * The specified dimension holds a float and should be multiplied by the
         * height or width of the object being animated.
         * 相对与自身的宽/高的百分比,1.0 == 100%
         */
        public static final int RELATIVE_TO_SELF = 1;
    
        /**
         * The specified dimension holds a float and should be multiplied by the
         * height or width of the parent of the object being animated.
         * 相对于父控件的百分比
         */
        public static final int RELATIVE_TO_PARENT = 2;
    

    demo

        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f);
        scaleAnimation.setDuration(2000);
        scaleAnimation.setFillAfter(true);
        alphaImageView.startAnimation(scaleAnimation);
    


    把构造方法加上pivot,
        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f, 175f, 175f);
    

    我们把缩放起点设置为175,那么它的缩放就从这个起点向两边开始缩放

        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);   
    

    我们把它的起点模式改为relative_to_self,pivotX 和 pivotY改为0.5,意思就是它的缩放起点变为这个view的宽高的中点,向两边放大至原来的1.5倍
    * @param fromXType Specifies how fromXValue should be interpreted. One of
     * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
     * Animation.RELATIVE_TO_PARENT.
    

    fromXType 就是用于解释解释fromCValue,其余的也是同样意思,和上面的ScaleAnimation

    TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 1.0f, 
    Animation.ABSOLUTE,0, Animation.ABSOLUTE, 0);
    
    translateAnimation.setDuration(2000);
    translateAnimation.setFillAfter(true);
    alphaImageView.startAnimation(translateAnimation);
    

    不放图了.....

    RotateAnimation

    RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f);
    rotateAnimation.setDuration(2000);
    rotateAnimation.setFillAfter(true);
    alphaImageView.startAnimation(rotateAnimation);  
    

    围绕图片中心转一圈,

    AnimationSet

    <?xml version="1.0" encoding="utf-8"?>
    <set
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fillAfter="true">
    
        <alpha
            android:fromAlpha="0.0"
            android:toAlpha="1.0"/>
        
        <scale
            android:fromXScale="0.1"
            android:fromYScale="0.1"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toXScale="1.0"
            android:toYScale="1.0"/>
    
        <translate
            android:fromXDelta="-50%p"
            android:toXDelta="0"/>
    </set>
    

    这里说一下50% 和 -50%p ,单纯只是%就是基于view本身,也就Animation.RELATIVE_TO_SELF,而%p就是基于view的parent,也就是Animation.RELATIVE_TO_PARENT.


    图中的view宽度为60px,父view为100px,左右两边平分,各为20px,针对view的动画

    <translate
            android:fromXDelta="-50%p"
            android:toXDelta="0"/>
    

    这个的意思就是:

    view动画的开始位置是:view在图中的位置向左移动距离(0.5 * 100 = 50 ,为什么是左,-50%p)px,就是view在图片当前的位置向左移动50px就开始动画,这个移动的过程当然是看不到的,并且这不是view真正的移动,这里只是文字表述,view其实一直不改变它所在的位置。

    结束位置就是view当前所在的位置,也就是view的左边距离父的左边20px

    Interpolator

    通过定义Interpolator可以改变动画的速率,比如加速,减速,匀速等,Android定义了一系列的interpolator


    accelerate decelerate interpolator

    动画开始和动画结束的时候速度较慢,中间的速度较快。默认的插值器就是这个,在xml中的引用

    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    

    accelerate interpolator

    动画从开始到结束的过程中一直加速,有个参数factor,就是设置速率的变化的,factor默认是1.0,factor的值越大 ,开始的速度就会变得更加慢,结束的速度更加快。

  1. TimeInterpolator 时间插值器
  2. fraction 一个0-1的分数,由Animator 根据 当前动画播放时间/duration ,再经过xxxInterpolator计算,不同的interpolator结果不一样
  3. TypeEvaluator 根据fraction的值计算出动画改变属性的属性值
  4. ValueAnimator

    ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setDuration(2000);//设置动画时间,默认是300
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());//设置插值器,默认也是这个
        valueAnimator.setFloatValues(0, 200);//设置开始值和结束值
    
    
        //监听属性值的改变 
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float tem = (float) animation.getAnimatedValue();
                Log.d(TAG, "onAnimationUpdate: " + tem);
                view.setTranslationY(tem);
    
            }
        });
        //开始动画
        valueAnimator.start();
    

    第一个参数就是动画应用在哪个对象,第二个参数就是设置这个动画改变的属性,第三个可变参数,写一个就是属性的开始值,两个就是一个开始值一个结束值。这里改变的属性值必须有setXxx方法,因为是通过反射调用设置这个属性的,还有就是这这个方法中必须包含对这个view 的重绘的方法,view.postInvalidate(); / view.invalidate();否则你设置了这个属性也不能在界面上马上看到效果,也就没有动画可言。
  5. addUpdateListener 每次对应的TypeEvaluate计算完属性值都会回调这个方法
  6. addListener 动画的开始结束取消重复监听,可以使用AnimatorListenerAdapter代替,自己选择监听哪个
  7. TypeEvaluate

    自定义TypeEvaluate

    实现抛物线,x方向是100px/s,y方向的加速度是200px/s*s

     ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator<PointF>() {
            @Override
            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
    
                PointF pointF = new PointF();
                //fuction = t /duration
                pointF.x = 100 * 2 * fraction;
                pointF.y = 0.5f * 200 * 2 * fraction * 2 * fraction;
    
                return pointF;
            }
        }, new PointF(0, 0));
    
        animator.setDuration(2000);
    
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF p = (PointF) animation.getAnimatedValue();
    
                view.setTranslationX(p.x);
                view.setTranslationY(p.y);
            }
        });
        animator.start();
    

    xml实现

    objectAnimator

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:interpolator="@android:anim/linear_interpolator"
        android:propertyName="y"
        android:valueFrom="0.0"
        android:valueTo="300.0"
        android:valueType="floatType">
    
    </objectAnimator>
    

        Animator animator = AnimatorInflater.loadAnimator(this, R.animator.value_animator);
        animator.setTarget(view);
        animator.start();
    

    animatorSet

    <?xml version="1.0" encoding="utf-8"?>
    <set
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering="together">
        <objectAnimator
            android:duration="3000"
            android:interpolator="@android:anim/linear_interpolator"
            android:propertyName="scaleX"
            android:valueFrom="1.0"
            android:valueTo="0.2"
            android:valueType="floatType"
            />
    
        <objectAnimator
            android:duration="3000"
            android:interpolator="@android:anim/linear_interpolator"
            android:propertyName="scaleY"
            android:valueFrom="1.0"
            android:valueTo="0.2"
            android:valueType="floatType"
            />
        <objectAnimator
            android:duration="3000"
            android:interpolator="@android:anim/linear_interpolator"
            android:propertyName="rotationX"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType"
            />
        
    </set>
    

    java

    AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.value_animator_set);
    set.setTarget(view);
    
    set.start();
    

    set中的一个参数就是ordering,顺序可以选择together(同一时间所有动画一起开始),也可以选择sequentially(按set中的顺序顺序一个个开始)。
    纯java animatorSet

    AnimatorSet set= new AnimatorSet();
    
        set.play(AnimatorInflater.loadAnimator(this, R.animator.value_animator)).
                with(new ObjectAnimator().setDuration(2000).ofFloat(view, "x", 0, 200));
    
    
        set.setTarget(view);
        set.setDuration(2000);
    
        set.start();
    

    https://github.com/lijinxiong/note/blob/master/Android/%E5%8A%A8%E7%94%BB.md

    相关文章

      网友评论

        本文标题:Android动画

        本文链接:https://www.haomeiwen.com/subject/pchotxtx.html