Android开发艺术探索 - 第7章 Android动画深入分析

Animation resources
Property Animation Overview

1.View动画

  1. Tween补间动画
    四种动画效果,平移TranslateAnimation、缩放ScaleAnimation、旋转RotateAnimation和透明度AlphaAnimation,xml中对应四种标签的定义方式(res/anim/xxx.xml):
    
    
        
        
        
        
        
            ...
        
    
    
    • 代表AniamtionSet类
      android:interpolator 插值器
      android:shareInterpolator 是否与子元素共享插值器

    • android:fromAlpha
      android:toAlpha

    • android:fromXScale
      android:toXScale
      android:fromYScale
      android:toYScale
      android:pivotX 缩放中心
      android:pivotY 缩放中心

    • 支持三种数据格式:-100100以%结尾,代表关于自身的比例;-100100以%p结尾,代表关于其父组件的比例;float值,绝对参数。
      android:fromXDelta
      android:toXDelta
      android:fromYDelta
      android:toYDelta

    • android:fromDegrees
      android:toDegrees
      android:pivotX 旋转中心,也支持三种数据格式:相对于父组件左边缘的%p,相对于自身左边缘的%,相对于自身左边缘的x
      android:pivotY
    • 其他常用属性:
      android:duration
      android:fillAfter 动画结束后是否停留在结束位置
    • 应用动画
    ImageView image = (ImageView) findViewById(R.id.image);
    Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
    image.startAnimation(hyperspaceJump);
    
    • 自定义插值器
      通过xml创建自己的插值器,然后引用现有的插值器,并修改其属性。如果不修改属性,则其表现相当于原始的插值器。
    
    
    

  • android:factor 加速度,默认1。

  • android:tension 张力,默认2。

  • android:tension
    android:extraTension 乘以tension,默认1.5。

  • android:cycles 循环次数,默认1。

  • android:factor 减速度,默认1。

  • android:tension 张力,默认2。
  1. Frame帧动画
    在xml中定义(res/drawable/xxx.xml),对应类AnimationDrawable。
    
    
        
    
    
    • android:oneshot
      是否播放一次。
    • 使用
      
      
          
          
          
      
      
      ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
      rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
      
      rocketAnimation = rocketImage.getBackground();
      if (rocketAnimation instanceof Animatable) {
          ((Animatable)rocketAnimation).start();
      }
      
  2. View动画其他应用
    • LayoutAnimation
      作用于ViewGroup的子元素,常用于ListView。
      1. 定义LayoutAnimation
        
        
        
        android:delay 播放动画开始前的延时
        android:animationOrder 动画播放顺序,normal/reverse/random
        android:animation 指定动画
      2. 定义动画
      3. 在为ViewGroup设置android:layoutAnimation,指向定义的LayoutAnimation。
    • Activity切换动画
      overridePendingTransition(int enterAnim, int exitAnim)
      在startActivity和finish之后调用。

2.属性动画

  1. 使用
    • xml定义,存放位置res/animator/xxx.xml
    
    
        
    
        
    
        
            ...
        
    
    

  • android:ordering 动画播放顺序:sequentially/together(default)

  • android:propertyName 属性名。如alpha/backgroundColor
    android:valueTo 需要指定。
    android:valueFrom 默认值通过getXX从target得到
    android:duration 默认300ms
    android:startOffset 调用start之后delay的时间
    android:repeatCount -1:无限循环;1:重复一次;0:不重复
    android:repeatMode 重复方式:reverse/repeat
    android:valueType intType/floatType,当animation color时不需要指定。

  • 除了没有propertyName,与objectAnimator相同。
  • 使用
    AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
        R.animator.property_animator);
    set.setTarget(myObject);
    set.start();
    
    • 代码
    ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
    animation.setDuration(1000);
    animation.start();
    
    animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator updatedAnimation) {
            // You can use the animated value in a property that uses the
            // same type as the animation. In this case, you can use the
            // float value in the translationX property.
            float animatedValue = (float)updatedAnimation.getAnimatedValue();
            textView.setTranslationX(animatedValue);
        }
    });
    
    ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
    animation.setDuration(1000);
    animation.start();
    
  1. 插值器和估值器
    自定义插值器需要实现Interpolator或TimeInterpolator接口,自定义估值器需要实现TypeEvaluator接口。如果需要对除了int/float/Color之外的属性做动画,则一定需要实现自定义估值器。
  2. 动画监听
    • Animator.AnimatorListener:监听动画开始/停止/取消/重复
      onAnimationStart()
      onAnimationEnd()
      onAnimationRepeat()
      onAnimationCancel()
    • AnimatorListenerAdapter:AnimatorListener的空实现
    • ValueAnimator.AnimatorUpdateListener 如果使用的是ValueAnimator,则需要实现该接口
      onAnimationUpdate() 在动画的每一帧回调
  3. 属性动画原理
    ValueAnimator调用start方法之后,在整个动画的过程中,ValueAnimator会基于已经逝去的时间计算elapsed fraction;之后调用TimeInterpolator将elapsed fraction映射为interpolated fraction;最后,基于start value,end value和interpolated fraction通过TypeEvaluator计算出当前的property value。ref
    ValueAnimator只实现了计算动画属性值的工作,将属性值更新到target的过程需要自己完成;ObjectAnimator则在ValueAnimator基础上,完成了设置属性值的工作。所以前者有更大的灵活性,在使用后者时,一些注意事项:
    • 设置的属性必须有其set方法,foo->setFoo。如果没有set方法,有三种选择:如果有权限,直接添加一个set方法;使用一个wrapper类包装原始对象,然后设置set方法;使用ValueAnimator。
    • 如果参数中只指定了一个value,即没有指定start value,则该属性必须要有get方法,foo->getFoo
    • set方法和get方法操作的类型要一致。
  4. ViewPropertyAnimator
    因为Android 3.0之前的View动画的局限性,属性动画得以引入。而对于View来说,属性动画得益于引入了相应的属性:
    • translationX/translationY
    • rotation/rotationX/rotationY
    • scaleX/scaleY
    • pivotX/pivotY
    • x(left + translationX)/y(top + translationY)
    • alpha
      同时提供了更方便的API去实现View的属性动画:
    ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
    ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
    AnimatorSet animSetXY = new AnimatorSet();
    animSetXY.playTogether(animX, animY);
    animSetXY.start();
    
    PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
    PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
    ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
    
    myView.animate().x(50f).y(100f);    // ViewPropertyAnimator
    

3.注意事项

  1. OOM问题->帧动画
  2. 内存泄漏->属性动画的无限循环,在Activity退出之后要停止
  3. 硬件加速
  4. View动画不能移动View本身,如果动画完成后,setVisibility(GONE)失效,需要调用view.clearAnimation()清除动画。

你可能感兴趣的:(编程,Android,Java)