美文网首页
Android 动画

Android 动画

作者: 特大碗牛肉面 | 来源:发表于2018-10-31 19:13 被阅读0次

    视图动画:

    AlphaAnimation、RotateAnimation、TranslateAnimation、ScaleAnimation 和 动画集:AnimationSet

    • AlphaAnimation(透明度动画):
    AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
    alphaAnimation.setDuration(1000);
    view.startAnimation(alphaAnimation);
    
    • RotateAnimation(旋转动画):
    RotateAnimation rotateAnimation = new RotateAnimation(0, 360, 
    RotateAnimation.RELATIVE_TO_SELF, 0.5F, RotateAnimation.RELATIVE_TO_SELF, 0.5F);
    rotateAnimation.setDuration(1000);
    view.startAnimation(rotateAnimation);
    
    • TranslateAnimation(位移动画):
    TranslateAnimation  translateAnimation = new TranslateAnimation(0, 200, 0, 0);
    translateAnimation.setDuration(1000);
    view.startAnimation(translateAnimation);
    
    • ScaleAnimation(缩放动画):
    ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, 
    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    scaleAnimation.setDuration(1000);
    view.startAnimation(scaleAnimation);
    
    • AnimationSet(动画集合):
    AnimationSet animationSet = new AnimationSet(true);
            animationSet.setDuration(4000);
            animationSet.addAnimation(alphaAnimation);
            animationSet.addAnimation(rotateAnimation);
            animationSet.addAnimation(translateAnimation);
            animationSet.addAnimation(scaleAnimation);
            animationSet.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    Log.e(TAG, "onAnimationStart: 动画开始执行的时候调用");
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                    Log.e(TAG, "onAnimationEnd: 动画结束执行的时候调用");
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
                    Log.e(TAG, "onAnimationRepeat: 动画重复执行的时候调用");
                }
            });
    //启动动画
    view.startAnimation(animationSet);
    

    属性动画

    PropertyValuesHolder、Animator、ObjectAnimator 、ValueAnimator

    • ObjectAnimator :

    ObjectAnimator 是属性动画框架中最重要的实行类,创建一个ObjectAnimator只需要通过它的静态工厂类直接返回一个ObjectAnimator对象.(通过ofxxx方法);
    必须具备get 、set方法,不然ObjectAnimator就无法起效;

    • 1.translationX 和 translationY:控制view对象从布局容器的左下方坐标偏移的位置;
    • 2.rotation 、rotationX 和 rotationY:控制view对象围绕它的支点进行2D和3D旋转;
    • 3.scaleX 和 scaleY: 控制view对象围绕它的支点进行2D缩放;
    • 4.pivotX 和 pivotY:这两个属性控制着View对象的支点位置, 围绕这个支点进行旋转和缩放变换处理;
      默认情况下,该支点的位置就是view的中心点;
    • 5.alpha:它表示view对象的alpha透明度,默认值是1(不透明) ,0代表完全透明(不可见);
      如果没有get set方法,那么可以自定义一个属性或者包装类,来间接地给这个属性增加get set方法, 或者通过ValueAnimator来实现;
    1. 自带属性:
    ObjectAnimator  objectAnimator = ObjectAnimator.ofFloat(view, "translationX", 200);
    objectAnimator.setDuration(1000);
    objectAnimator.start();
    
     ObjectAnimator animatorColor = ObjectAnimator.ofInt(view,"BackgroundColor",0xffff0000,0xff00ff00);
    animatorColor.setEvaluator(new ArgbEvaluator());
    animatorColor.setDuration(1000);
    animatorColor.start();
    
    1. 自定义属性:
    public class WrapperView {
    
        private View view;
    
        public WrapperView(View view) {
            this.view =view;
        }
    
        public int getWidth(){
            return view.getLayoutParams().width;
        }
    
        public void setWidth(int width) {
            view.getLayoutParams().width = width;
            view.requestLayout();
        }
    }
    
    WrapperView wrapperView = new WrapperView(tvWrapper);
    ObjectAnimator objectAnimatorWrapper = ObjectAnimator.ofInt(wrapperView, "width", 100).setDuration(1000);
            objectAnimatorWrapper.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    Log.e(TAG, "onAnimationStart: 动画开始执行的时候调用");
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    //这个应该是用得最多的吧
                    Log.e(TAG, "onAnimationEnd: 动画结束执行的时候调用");
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
                    Log.e(TAG, "onAnimationEnd: 动画取消执行的时候调用");
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
                    Log.e(TAG, "onAnimationEnd: 动画重复执行的时候调用");
                }
            });
    objectAnimatorWrapper.start();
    

    • PropertyValuesHolder:

    类似AnimationSet

    1. 动画合并:
    PropertyValuesHolder valuesHolderTranslastion = PropertyValuesHolder.ofFloat("translationX", 100f);
    PropertyValuesHolder valuesHolderScaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.3f);
    PropertyValuesHolder valuesHolderScaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.3f);
    PropertyValuesHolder valuesHolderColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xff888888, 0xff00ff00);
    ObjectAnimator objectAnimatorProper = ObjectAnimator.ofPropertyValuesHolder(tvObjProperty, valuesHolderTranslastion, valuesHolderScaleX, valuesHolderScaleY, valuesHolderColor);
    objectAnimatorProper.setDuration(1000);
    objectAnimatorProper.start();
    
    1. 动画拆分:
     // 在 0% 处开始向X移动
    Keyframe keyframe1 = Keyframe.ofFloat(0, 0);
    // 时间经过 50% 的时候,动画完成度 100%
    Keyframe keyframe2 = Keyframe.ofFloat(0.5f, 100);
    // 时间见过 100% 的时候,动画完成度倒退到 0%位置
    Keyframe keyframe3 = Keyframe.ofFloat(1, 0);
    PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", keyframe1, keyframe2, keyframe3);
    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(tvObjPropertyKey, holder);
    animator.start();
    

    • ValueAnimator:

    ValueAnimator 是 ObjectAnimator 的父类,ValueAnimator 就是一个不能指定目标对象版本的 ObjectAnimator

    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1000);
            valueAnimator.setTarget(view);
            valueAnimator.setDuration(1000);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                  // TODO: 2018/10/24
                    float value = (float) animation.getAnimatedValue();
                    if (value==500f){
                        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
                        scaleAnimation.setDuration(100);
                        view.startAnimation(scaleAnimation);
                    }
                }
            });
    

    • Animator:

    res/animator下创建布局文件,代码加载xml布局文件

    <?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 animatorXml = AnimatorInflater.loadAnimator(MainActivity.this,R.animator.animator_xml);
    animatorXml.setTarget(view);
    animatorXml.start();
    

    AnimationUtils (工具类)

    • Android SDK 提供的工具类:
    返回值 公共方法 描述
    static long currentAnimationTimeMillis() 以毫秒返回当前动画时间
    static Animation loadAnimation(Context context, int id) 从资源加载动画对象
    static Interpolator loadInterpolator(Context context, int id) 从资源中加载内插器对象
    static LayoutAnimationController loadLayoutAnimation(Context context, int id) 从资源加载动画对象(返回值不同)
    static Animation makeInAnimation(Context c, boolean fromLeft) 用布尔参数决定滑入的方向是左侧还是右侧向上
    static Animation makeInChildBottomAnimation(Context c) 视图总是从屏幕的底部向上滑入
    static Animation makeOutAnimation(Context c, boolean toRight) 用布尔参数决定滑入的方向是左侧还是右侧
    animation = AnimationUtils.loadAnimation(this, R.anim.animation_utils);
    view.startAnimation(animation);
    

    ViewAnimationUtils (5.X的工具类)

    createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius)

    • centerX : 中心点X坐标;
    • centerY : 中心点Y坐标;
    • startRadius: 动画圆的起始半径;
    • endRadius: 动画圆的结束半径.
    ViewAnimationUtils.createCircularReveal(ImageView, centerX, centerY, mImageView.getWidth(), 0);
    

    Interpolator(插值器)

    Interpolator 其实就是速度设置器。你在参数里填入不同的 Interpolator ,动画就会以不同的速度模型来执行;Google TimeInterpolator

    • AccelerateDecelerateInterpolator:

    先加速再减速。这是默认的 Interpolator;

    • LinearInterpolator:

    匀速;

    • AccelerateInterpolator:

    持续加速;

    • DecelerateInterpolator:

    以最高速开始,持续减速直到停止;

    • AnticipateInterpolator:

    先回退一下段,然后再正常运动;

    • OvershootInterpolator:

    到终点的时候超出一下段,然后弹回来;

    • AnticipateOvershootInterpolator:

    开始前回拉,最后超过一些然后回弹;

    • BounceInterpolator:

    到达终点的时候弹回来两下,然后回到终点;

    • CycleInterpolator:

    这个也是一个正弦 / 余弦曲线,不过它和 AccelerateDecelerateInterpolator 的区别是,它可以自定义曲线的周期,所以动画可以不到终点就结束,也可以到达终点后回弹,回弹的次数由曲线的周期决定,曲线的周期由 CycleInterpolator() 构造方法的参数决定。

    • PathInterpolator:

    自定义动画完成度 / 时间完成度曲线。
    用这个 Interpolator 你可以定制出任何你想要的速度模型。定制的方式是使用一个 Path 对象来绘制出你要的动画完成度 / 时间完成度曲线

    • FastOutLinearInInterpolator(5.0以上):

    贝塞尔曲线的持续加速的运动路线,AccelerateInterpolator比FastOutLinearInInterpolator斜率要低一点;

    • FastOutSlowInInterpolator(5.0以上):

    贝塞尔曲线,前期加速度要快得多;

    • LinearOutSlowInInterpolator(5.0以上):

    减速曲线,初始速度更高;


    SVG(矢量动画)

    • Android 5.X增加了对SVG矢量图的支持(VectorDrawable,AnimatedVectorDrawable):
      <path>标签支持的指令:
    • M: 移动 moveTo;
    • L: 直线;
    • H: 水平线;
    • V: 垂直线;
    • C: 三次贝塞尔曲线;
    • S: 三次贝塞尔曲线;
    • Q: 二次贝塞尔曲线;
    • T: 映射前面路径后的终点;
    • Z: 关闭路径;
    • A: 弧线;
    • RX,RY表示椭圆半圆的半轴大小;
    • XROTATION表示X轴与水平方向的顺时针方向的夹角;
    • FLAG1有两个值:1.表示大角度的弧线,0.表示小角度弧线;
    • FLAG2有两个值,确定从起点至终点的方向:1.表示顺时针,0.表示逆时针;
    • X,Y轴为终点坐标;

    1.大小写效果一样,2.坐标轴和canvas一样左上角(0,0),3.指令和数据间的空格可以省略,4.同个指令出现多个时候可以只用一个。

       defaultConfig {
            //配置信息
            vectorDrawables.useSupportLibrary = true
        }
    <!--res/drawable下新建-->
    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="100dp"
        android:width="100dp"
        android:viewportWidth="100"
        android:viewportHeight="100">
        <group>
            <path
                android:name="path1"
                android:strokeColor="@color/colorPrimaryDark"
                android:strokeWidth="5"
                android:strokeLineCap="round"
                android:pathData="M 20,80 L 50,80 80,80"/>
        </group>
    
        <group>
            <path
                android:name="path2"
                android:strokeColor="@color/colorPrimaryDark"
                android:strokeWidth="5"
                android:strokeLineCap="round"
                android:pathData="M 20,20 L 50,20 80,20"/>
        </group>
    </vector>
    
    
    <!--res/animator下新建-->
    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="pathData"
        android:valueFrom="M 20,80 L 50,80 80,80"
        android:valueTo="M 20,80 L 50,50 80,80"
        android:valueType="pathType"
        android:interpolator="@android:anim/bounce_interpolator">
    </objectAnimator>
    
    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:propertyName="pathData"
        android:valueFrom="M 20,20 L 50,20 80,20"
        android:valueTo="M 20,20 L 50,50 80,20"
        android:valueType="pathType"
        android:interpolator="@android:anim/bounce_interpolator">
    
    </objectAnimator>
    
    <!--res/drawble-v21下新建-->
    <?xml version="1.0" encoding="utf-8"?>
    <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/svg_line">
    
        <target
            android:name="path1"
            android:animation="@animator/animator_svg_path1"/>
    
        <target
            android:name="path2"
            android:animation="@animator/animator_svg_path2"/>
    </animated-vector>
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        Drawable drawable = imageViewSVG.getDrawable();
                        if (drawable instanceof Animatable){
                            ((Animatable) drawable).start();
                        }
                    }
    

    SVG编辑器链接
    本项目的简单Demo地址


    相关文章

      网友评论

          本文标题:Android 动画

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