《Andorid开发艺术探索第七章》-动画

Android动画深入分析

Android动画可以分为三种:View动画、帧动画和属性动画

View动画

  1. Heading
名称标签子类效果
平移动画<translate>TranslateAnimation移动View
缩放动画<scale>ScaleAnimation放大或缩小View
旋转动画<rotate>RotaAnimation旋转View
透明度动画<alpha>AlphaAnimation改变VIew的透明度

2. android:interpolator:表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。默认为@android:anim/accelerate_decelerate_interpolator即加减速插值器
android:shareInterpolator表示集合中的动画是否和集合共享同一个插值器。
3. 自定义动画的时候只需要继承Animation这个抽象类,然后重写它的initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中进行相应的矩阵变化即可。
4. 帧动画:使用比较简单,但是使用比较容易引起OOM,所以在使用帧动画时应尽量避免使用过大的图片。

View动画的特殊使用场景

  1. LayoutAnimation作用于VIewGroup,为VIewGroup指定一个动画
    给VIewGroup的子元素加上出场效果
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:delay = "0.5"
    android:animationOrder = "normal"
    android:animation="@anim/anim_item"
    >
</layoutAnimation>

android:delay表示子元素开始动画的时间延迟,比如子元素入场动画的时间周期为300ms,那么0.5表示每个子元素都需要延迟150ms才能入场。
android:animationOrder有三种选项:normal/reverse和random,其中normal表示顺序显示,reverse表示你想显示,random表示随机播放入场动画

 ListView listView = (ListView)findViewById(R.id.list);
 Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
 controller.setDelay(0.5f);
 controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
 listView.setLayoutAnimation(controller);
  1. 切换动画主要用到overridePendingTransition(int enterAnim, int exitAnim)这个方法,必须在startActivity(Intent)或者finish()之后被调用才能生效

属性动画

属性动画中有ValueAnimator、ObjectAnimator和AnimatorSet

1.属性动画可以对任意对象的属性进行动画而不仅仅是VIew,动画默认时间间隔为300ms,默认帧率10ms/帧.
2.其中ObjectAnimator继承自ValueAnimator,AnimatourSet是动画集合。Nineoldandroids对属性动画做了兼容,在API以前的版本其内部是通过代理VIew动画来实现的。
3.

  //加载属性动画需要用到AnimatorInflater类
ObjectAnimator oa = (ObjectAnimator) AnimatorInflater.loadAnimator(MainActivity.this, R.animator.objectdemo);
//用于动画计算的需要,如果开始和结束的值不是基本类型的时候,这个方法是需要的。
 oa.setEvaluator(new ArgbEvaluator());
 //设置动画的设置目标
 oa.setTarget(imageView);
 oa.start();

4.
属性动画需要定义在res/animator目录下,它的语法如下;

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially"
    >

<objectAnimator
//表示属性动画的作用对象的属性的名称
    android:propertyName="@string/app_name"
    //表示动画的时长
    android:duration="int"
    //表示属性的起始值
    android:valueFrom="int"
    //表示属性的结束值
    android:valueTo="int"
    表示动画的延迟时间,需要延迟多少毫秒才能真正播放此动画
    android:startOffset="int"
    //表示动画的重复次数
    android:repeatCount="int"
    //表示动画的重复模式
    android:repeatMode="restart"
    //表示android:propertyName指定的属性类型,另外如果所指定的属性表示颜色,那么不需要指定android:valueType,系统会自动对颜色类型的属性做处理
    android:valueType="intType"
    />

</set>
  1. 插值器和估值器
    TimeInterpolator为时间插值器,作用为根据时间流逝的百分比来计算当前属性值改变的百分比。LinearInterpolator表示匀速动画
    TypeEvaluator为类型估值算法。作用是根据当前属性改变的百分比来计算改变后的属性值。
    属性动画要求对象的该属性有set方法和get方法
    自定义插值器需要实现Inter或者TimeInterpolator,自定义估值器需要实现TypeEvaluator

FloatEvaluator的代码实现

public class FloatEvaluator implements TypeEvaluator {  
        public Object evaluate(float fraction, Object startValue, Object endValue) {  
            float startFloat = ((Number) startValue).floatValue();  
            return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);  
        }  
    }  
  1. AnimtorUpdateListener
    public static interface AnimatorListenre{
    //开始
        void onAinmationStrart(Animatior animator);
        //结束
        void onAinmationEnd(Animatior animator);
        //取消
        void onAinmationCancel(Animatior animator);
        //重复播放
        void onAInmarionRepeat(Animatior animation)
}
public static interface AnimatorUpdateListener{
    void onAnimationUpdate(ValueAnimator animation);
}

监听整个动画过程,动画是由许多帧组成的,每播放一帧,OnAnimationUpdate就会被调用一次。
7. 对Object的属性abc做动画,如果想让动画生效,要同时满足两个条件:
(1) object必须要提供setAbc方法,如果动画的时候没有传递初始值,那么还要提供getAbc方法,因为系统要去取abc属性的初始值
(2) object的setAbc对属性abc所做的改变必须能够通过某种方法反映出来,比如会带来UI的改变之类的。

  1. 在对Button的width属性做动画没有效果,是因为他是继承了TextView,所以有了setWidth方法。
    3种解决办法

    1. 给对象加上get和set方法,如果有权限的话,(要在Android SDk内部实现)
    2. 用一个类来包装原始对象,间接为其提供get和set方法

      private void perfornAnimate(){
          ViewWrapper wrapper = new ViewWrapper(mBuutton);
          ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
      }
      
      private static class ViewWrapper{
          private View mTarget;
      
          public ViewWrapper(View target){
              mTarget = target;
          }
      
          public int getWidth(){
              return mTarget.getLayoutParams().width;
          }
      
          public void setWidth(int width){
              mTarget.getLayoutParams().width = width;
              mTarget.requestLayout();
          }
      }
    3. caiyongValueAnimator,监听动画过程,自己实现属性的改变

8.属性动画原理

要求动画作用的对象提供该属性的set方法,属性动画根据你传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,每次传递给set方法的值都不一样,确切来说是随着时间的推移,所传递的值越来越接近最终值。

属性动画需要运行Looper的线程中,set和get方法在内部中都是通过反射来调用的

注意事项

  1. View动画是对View影象做动画,并不是真正的改变View的状态,因此有时候会出现动画完成后VIew无法隐藏的现象,即setVIsibility(View.GONE)失效,这个时候只要调用view.clearAnimation()清除View动画即可解决此问题。
  2. 不要使用px,尽量使用dp
  3. 在3.0开始,属性动画的单击事件触发位置为移动的位置,但是VIew动画仍然砸原位置。

组合动画

实现组合动画功能主要需要借助AnimatorSet这个类,这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

after(Animator anim)   将现有动画插入到传入的动画之后执行
after(long delay)   将现有动画延迟指定毫秒后执行
before(Animator anim)   将现有动画插入到传入的动画之前执行
with(Animator anim)   将现有动画和传入的动画同时执行

我们想要让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);  
    ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);  
    ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
    AnimatorSet animSet = new AnimatorSet();  
    animSet.play(rotate).with(fadeInOut).after(moveIn);  
    animSet.setDuration(5000);  
    animSet.start();  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值