美文网首页安卓
Android26-动画机制与使用技巧

Android26-动画机制与使用技巧

作者: figure_ai | 来源:发表于2017-05-25 09:26 被阅读66次

    Android View动画

    Animation 框架定义了透明度、旋转、缩放和位移几种常见的动画,而且控制的是整个View。

    • 以下是一些常用动画的设置
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
        public void btnAlpha(View view) {
            AlphaAnimation aa = new AlphaAnimation(0, 1);
            aa.setDuration(3000);
            view.startAnimation(aa);
        }
        public void btnRotate(View view) {
            //0 :旋转起始角度
            //360 : 旋转终止角度
            //0,0 :绕那个点旋转
            RotateAnimation ra = new RotateAnimation(0, 270, 0, 0);
            ra.setDuration(3000);
            view.startAnimation(ra);
        }
        public void btnRotateSelf(View view) {
            RotateAnimation ra = new RotateAnimation(0, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            ra.setDuration(3000);
            view.startAnimation(ra);
        }
        public void btnTranslate(View view) {
            //0 : x起始位置
            //200 :x结束位置
            //0 : y起始位置
            //300 :y结束位置
            TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
            ta.setDuration(3000);
            view.startAnimation(ta);
        }
        public void btnScale(View view) {
            //1 : x起始大小
            //1 : x结束大小
            //0 : y起始大小
            //2 : y结束大小
            ScaleAnimation sa = new ScaleAnimation(1, 1, 0, 2);
            sa.setDuration(3000);
            view.startAnimation(sa);
        }
        public void btnScaleSelf(View view) {
            ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            sa.setDuration(3000);
            view.startAnimation(sa);
        }
        public void btnSet(View view) {
            //动画组
            AnimationSet as = new AnimationSet(true);
            as.setDuration(3000);
            //透明度动画
            AlphaAnimation aa = new AlphaAnimation(0, 1);
            aa.setDuration(3000);
            as.addAnimation(aa);
            //平移动画
            TranslateAnimation ta = new TranslateAnimation(0, 100, 0, 200);
            ta.setDuration(3000);
            as.addAnimation(ta);
            //启动动画
            view.startAnimation(as);
        }
    }
    

    Android属性动画

    由于Animation框架改变的只是显示效果,并不能相应事件, 因此,在Android3.0之后引入了属性动画框架(Animator);Animator框架中使用最多的是AnimatorSet和ObjectAnimator的配合。

    • ObjectAnimator

    ObjectAnimator是属性动画框架中的最重要的实行类,创建一个ObjectAnimator只需通过他的静态工厂类直接返回一个ObjectAnimator对象,参数包括一个对象和对象的属性,但属性必须有get和set函数。

    ObjectAnimator animator = ObjectAnimator.ofFloat(
          view,
          "translationX",
          300);
    animator.setDuration(300);
    animator.start();
    

    ObjectAnimator : 常用动画属性说明

    • translationX 和 translationY :这两个属性通常用来控制view的平移。
    • rotaion、rotationX、rotationY :这三个属性控制view对象围绕支点进行2D和3D旋转。
    • scaleX 和 scaleY :这两个属性控制view对象围绕它的支点进行2D缩放。
    • pivotX 和 privotY :这两个属性控制view对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点位置就是view对象的中心点。
    • x 和 y :这两个属性描述了view对象在它的容器中的最终位置,它是最初的做坐标和tranlationX 和 translationY值的累计和。
    • alpha : 表示view对象的alpha透明度,默认值是1(不透明),0代表完全透明(不可见)。

    注:如果一个属性没有get、set方法,也通过包装类的方法给属性增加get、set方法来实现动画,代码如下:

    >     private static class WrapperView {
            private View mTarget;
            public WrapperView(View target) {
                mTarget = target;
            }
            public int getWidth() {
                return mTarget.getLayoutParams().width;
            }
            public void setWidth(int width) {
                mTarget.getLayoutParams().width = width;
                mTarget.requestLayout();
            }
        }
    

    通过以上代码,就给属性提供了set、get方法,使用时只需要操作包装类即可

    > WrapperView wrapper = new WrapperView(view);
    ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(3000).start();
    
    • PropertyValuesHolder

    类似视图动画的AnimationSet,属性动画如果对同个对象要定义多个属性,就要用刀PropertyValuesHolder来实现。

    >  //同时操作多个属性动画
    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(3000).start();
    
    • ValueAnimator

    ValueAnimator在属性动画中占有非常重要的地位,他本身不提供任何动画效果,他更像一个数值产生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程。

    > //ValueAnimator
    ValueAnimator animator = ValueAnimator.ofFloat(0, 400);
    animator.setTarget(view);
    animator.setDuration(1000).start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     @Override
     public void onAnimationUpdate(ValueAnimator animation) {
         Float value = (Float) animation.getAnimatedValue();
         //TODO use the value
         if (value < 200) {
             ObjectAnimator.ofFloat(view, "translationX", 200).setDuration(1000).start();
         } else {
             ObjectAnimator.ofFloat(view, "translationY", 200).setDuration(1000).start();
         }
     }
    });
    
    • 动画事件的监听

    一个完整的动画具有Start、Repeat、End、Cancel四个过程,通过Android提供的API可以很方便的监听这四个事件

    >         ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
           animator.addListener(new Animator.AnimatorListener() {
               @Override
               public void onAnimationStart(Animator animation) {
               //动画开始时  
               }
               @Override
               public void onAnimationEnd(Animator animation) {
               //动画结束时
               }
               @Override
               public void onAnimationCancel(Animator animation) {
               //动画取消时
               }
               @Override
               public void onAnimationRepeat(Animator animation) {
               //动画重复时
               }
           });
    
    • AnimatorSet

    对于一个对象同时作用多个属性动画,可以用PropertyValuesHolder实现,同样也可以用AnimatorSet实现,而且AnimatorSet同时也能实现更为精确的顺序控制。

    >//使用AnimatorSet实现作用多个动画
    ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
    ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
    ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
    AnimatorSet set = new AnimatorSet();
    set.setDuration(1000);
    set.playTogether(animator1, animator2, animator3);
    set.start();
    

    AnimatorSet正是通过playTogether()、playSequentially()、animSet.play().with()、before、after()等方法来对多个动画的播放顺序做精确的控制的。

    • View的animate方法

    在Android3.0之后,google给view增加了animate方法来直接设置属性动画。代码如下

    >//通过view的animate方法直接设置属性动画
            view.animate().alpha(0).y(300).setDuration(3000).withStartAction(new Runnable() {
                @Override
                public void run() {
                    //动画开始时
                }
            }).withEndAction(new Runnable() {
                @Override
                public void run() {
                    //动画结束时
                }
            }).start();
        }
    

    Android布局动画

    布局动画,是指作用在ViewGroup上的动画,当ViewGroup增加view时添加一个动画的过渡效果。
    最简单的布局动画是在ViewGroup的XML中,使用以下代码来设置

    android:animateLayoutChanges="true"
    

    另外还可通过LayoutAnimationController类来自定义一个子View的过渡效果。

    LinearLayout ll = (LinearLayout)findViewById(R.id.ll);
    //设置过渡动画
    ScaleAnimation sa = new ScaleAnimation(0, 1, 0,1);
    sa.setDuration(2000);
    //设置布局动画的显示属性
    LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);
    lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
    //为ViewGroup设置布局动画
    ll.setLayoutAnimation(lac);
    

    LayoutAnimationController的第一个参数是需要作用的动画,第二个参数是每个子view的显示时间,当delay时间不为0时可以设置子view显示的顺序

    • LayoutAnimationController.ORDER_NORMAL--正序
    • LayoutAnimationController.ORDER_RANDOM -- 随机
    • LayoutAnimationController.ORDER_REVERSE -- 反序
    • Interpolators(插值器)

    通过插值器,可以定义动画变换的速率,有点类似于物理中的加速度。主要作用是用来控制目标变量的变化值然后进行对应的操作。

    自定义动画

    创建自定义动画,通常情况下只需要覆盖父类的initialize方法来实现一些初始化工作,并且实现applyTransformation逻辑就可以了。

    > public
    class
    CustomAnim 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());
           mCenterHeight = height/2;
           mCenterWidth = width/2;
       }
       //暴漏一个接口给外界设置旋转角度
       public void setRotateY(float rotateY) {
           mRotateY = rotateY;
       }
       @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);
       }
    }
    
    

    在上面这个例子中用到了Camera,这里的Camera不是指手机中的相机,而是android.graphics.Camera中的Camera类,它封装了openGL的3D动画,从而可以非常方便的创建3D动画效果。使用的时候就是通过设置三个坐标轴(X、y、z)的旋转角度,从而实现3d动画的效果

    >mCamera.save();
    //使用Camera设置旋转的角度
    mCamera.rotateY(mRotateY * interpolatedTime);
    mCamera.rotateY(mRotateY * interpolatedTime);
    mCamera.rotateZ(mRotateY * interpolatedTime);
    //将旋转变化作用到matrix上
    mCamera.getMatrix(matrix);
    mCamera.restore();
    

    SVG矢量动画

    SVG : 可伸缩适量图形,于Bitmap(位图)相比,最明显的优点是放大不会失真。

    • <path> 标签

    使用<path>标签创建SVG,就像用指令的方式来控制一只画笔,例如移动画笔到某一坐标位置,画一条直线,画一条曲线等。常用<path>指令有以下几种:

    • M = moveto(M X, Y) : 将画笔移动到指定的坐标位置,但未发生绘制。
    • L = lineto(L X, Y) : 画直线到指定的坐标位置
    • H = horizontal lineto(H X) : 画水平线到指定的x坐标位置。
    • V = vertical lineto(V Y) : 画垂直线到指定的Y坐标位置。
    • C = curveto(C X1, Y1, x2, Y2, ENDX, ENDY) : 三次贝塞尔曲线。
    • S = smooth curveto(S X2, Y2, ENDX, ENDY) : 三次贝塞尔曲线。
    • Q = quadraic Belzier curve(Q X, Y, ENDX, ENDY) : 二次贝塞尔曲线。
    • T = smooth quadratic Belzier curveto(T ENDX, ENDY) : 映射前面路径后的终点。
    • A = cliptical Arc(A RX, RY, XROTATION, FLAG1, FLAG2, x, y) : 弧线。
    • Z = closepath() : 关闭路径。

    注:使用这些指令需注意以下几点

    • 坐标轴以(0, 0) 为中心,X轴水平向右, Y轴水平向下。
    • 所有指令大小写均可,大写表示绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系。
    • 指令和数据间的空格可以省略。
    • 同一指令出现多次可以只用一个。
    • Android中使用SVG

    Goggle在Android5.x中提供了VectorDrawable和AnimatedVectorDrawable两个API来帮助支持SVG,首先使用VectorDrawable来创建基于XML的SVG图形,再结合AnimatedVectorDrawable来实现动画效果。

    相关文章

      网友评论

        本文标题:Android26-动画机制与使用技巧

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