zoukankan      html  css  js  c++  java
  • Android动画的深入分析

    一、AnimationDrawable的使用

    详见:Drawable类及XMLDrawable的使用

    补充:通过Animation的setAnimationListener()可以给View动画添加监听过程

    二、自定义View动画(略,以后有空补上)

    三、帧动画

    定义:顺序播放一组预先定义好的图片。

    使用:①、在res/drawable/中定义<animation-list>标签 ②、在java代码中start使用

    <animation-list>
      <item android:drawable="@mipmap/img_1" android:duration="500"/>
      <item android:drawable="@mipmap/img_2" android:duration="500"/>
    </animation-list>
    frame_animation.xml
    Button btn = (Button)findViewById(R.id.main_btn);
    AnimationDrawable animation = (AnimationDrawable)btn.getBackground();
    //开启动画
    animation.start()
    MainActivity.java

    四、View动画的特殊使用

    (一)、LayoutAnimation

    作用:作用于ViewGroup,当其子元素出场的时候,都会具有这种动画效果(常用于ListView中)

    使用:①、在res/anim中创建layoutAnimation ②、在res/anim中创建实现的动画 ③、在layout中使用

    <layoutAniamtion
      android:delay = "0.5"
      android:animationOrder = "normal"
      android:animation = "@anim/anim_item"/>
    
    <!--andorid:delay  表示元素需要延迟多久才能播放动画
          andorid:animationOrder 表示子元素动画的顺序 有 normal:顺序显示 reverse:逆向显示 random:随机播放入场动画
          andorid:aniamtion 表示指定播放的动画-->
    anim_layout
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <alpha android:fromAlpha="0.5"
               android:toAlpha="1"/>
        <translate
            android:fromXDelta="0.0"
            android:toXDelta="500"/>
    </set>
    anim_item
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.maikefengchao.tabteamproject.MainActivity">
    
        <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            <!---设置动画的属性->
            android:layoutAnimation="@anim/anim_ilayout"></ListView>
    </RelativeLayout>

    在代码中加载动画:

      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ListView lv = (ListView)findViewById(R.id.main_lv);
            //获取anim_item
            Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_item);
            //代码创建LayoutAnimation
            LayoutAnimationController controller = new LayoutAnimationController(animation);
            //配置参数
            controller.setDelay(0.5f);
            controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
            //ListView加载LayoutAnimation
            lv.setLayoutAnimation(controller);   
        }
    MainActivity.java

    (二)Acitivty与Fragment的切换效果

    Activity:

    用到的方法:overridePendingTransition(int enterAnim,int exitAnim)。

    注:这个方法必须在startActivity()或finish()之后调用才生效。

    举例:

      @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn = (Button)findViewById(R.id.main_btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MainActivity.this,SecondActivity.class);
                    startActivity(intent);
                    //在startActivity()下使用,第一个参数表示SecondActivity的入场方式,第二个参数表示MainActivity的退出方式
                    overridePendingTransition(R.anim.show_second,R.anim.hide_main);
                }
            });
        }
    MainActivity
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
        }
    
        @Override
        public void finish() {
            super.finish();
            //在finish()方法后,                //在startActivity()下使用,第一个参数表示MainActivity的入场方式,第二个参数表示SecondActivity的退出方式
            overridePendingTransition(R.anim.show_main,R.anim.hide_second);
        }
    SecondActivity

    Fragment:
    setCustomAnimations()方法为Fragment添加动画效果

    五、属性动画

    定义:可以对任意对象的属性进行动画不仅仅是View,默认间隔300ms。

    作用:在一个时间间隔中将一个属性值改变成另一个属性值

    简介:常用的几个动画类ValueAnimator、ObjectAnimator(继承自ValueAnimator)、AnimatorSet

    ObjectAnimator:改变一个对象的属性

    ValueAnimator:设置时间,重复等特效

    AnimatorSet:为ObjectAnimator动画的合集

    使用:

    Java代码中

    /*ObjectAnimator的使用*/
    ObjectAnimator.ofFloat(myView,"translationY",0.1,100.5).start();
    //解析:ofFloat方法,如果输入的参数是int则调用 ofInt方法。参数:View,需要修改的属性,初始值,转换值。最后start()启动
    ObjectAnimator
    //改变属性
    VlueAnimator colorAnim = ObjectAnimator.ofInt(mView,"backgroundColor",/*white*/0x000,/*gray*/0x999);
    //配置
    colorAnim.setDuration(100);
    colorAnim.setRepeatCount(ValueAnimator.INFINITE);
    colorAnim.start();
    ValueAnimator
    AnimationSet set = new AnimationSet();
    set.playTogether(
      ObjectAnimator.ofFloat(myView,"rotationX",0,360),
      ObjectAnimator.ofFloat(myView,"rotationY",0,90),
      ...
    );
    set.setDuraction(5*1000).start();
    AnimatorSet

    在Xml中,在res/animator目录下,可以定义三个动画类(实际开发中建议采用java代码)

    <set>——AnimatorSet                  <animator>——ordering                <objectAnimation>——ObjectAnimation

    使用:

    参数解析:

    <set>中的属性:android:ordering属性有together:子动画同时播放 sequentially:子动画顺序播放

    剩下标签中的属性:

    android:propertyName——表示作用对象的属性名称(修改对象的哪个属性)

    android:duration——动画时长

    android:valueFrom——属性的起始值

    android:valueTo——属性的终止值

    android:startOffest——播放动画的延迟时间

    android:repeatCount——重复播放的次数(默认为0,-1为无限循环)

    android:repeatMode——有repeat:连续重复  reverse:逆向重复,指第一次播放完之后,第二次倒着播放,第三次再正这播放,以此类推。

    android:valueType——有intType/floatType,类似ofFloat/ofInt

    在java中调用:

    //获取对象
    AnimatorSet set = (AnimatortSet)AnimatorInflater.loadAnimator(this,R.anim.property_animator);
    //装载在哪个View上
    set.setTarget(mButton);
    //启动动画
    set.start();
    MainActivity.java

    六、插值器(Interpolator)和估值器(Evaluator)

    插值器

    作用:根据时间的流逝的百分比计算当前属性值改变的百分比。

    系统预制:LinearInterpolator(匀速动画)、AccelerateDecelerateInterpolator(两头慢中间快)、DecelerateInterpolator(动画越来越慢)

    估值器:

    作用:根据当前属性改变的百分比,计算出改变后的属性值

    系统预置:IntEvaluator(针对整型)、FloatEvaluator(针对浮点型)、ArgbEvaluator(针对Color属性)

    (二)两者关系

    匀速动画:采用线性插值,和整体估值法。

    举例:View的X属性从0~40的变换。当默认动画为10ms/帧时候,当t=20的时候,则百分比为0.5(即插值器为0.5),带入到估值器中返回的结果X就是20

    如果对其他类型做动画,就必须自定义估值器和插值器(详见P281)

    七、对任意属性做动画

    属性动画的原理:要求动画作用的对象提供该属性的get和set方法,属性动画根据外界传递的该属性的初始值和最终值,以动画的效果多次调用set方法。

    所以说,要让动画生效,必须满足:

    (1)object提供setXxx()方法,如果动画没有传递初始值,还要有getXxx()方法

    (2)setXxx()属性做的改变必须通过某种方法反映出来。(否则动画无效果)

    解决方法:

    (一)用一个类来包装原对象,简介为其提供set和get方法

    原理:原理创建一个类,里面有get、set方法,只要将View当成参数放进去就可以了。

    举例:利用动画伸长Button的宽。

    private void performAnimate(){
        ViewWrapper wrapper = new ViewWrapper(mButton);
        ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();  
    }
    //点击进行转换
    public void onClick(View v){
      if (v == mButton){
        performAnimate();
      }
    }
    //创建包装类
    private static class ViewWrapper{
      private View mTarget;
      
      pubic ViewWrapper(View target){
          mTarget = target;
      }
      //提供获取宽度的方法
      public int getWidth(){
        return mTarget.getLayoutParams().width;
      }
      //提供修改宽度的方法
      public void setWidth(int width){
        mTarget.getLayoutParams.width = width;
        mTarget.requestLayout();
      }
    }    
    View Code

    (二)采用ValueAnimator,监听动画过程,实现自定义属性改变。

    原理:创建ValueAnimator对象,设置AnimatorUpadateListener()监听器,之后动画的每一帧都会调用其onAnimationUpdate()方法,在该方法内,设置宽高。其原理和(一)相同。

    举例:

    //参数:作用对象,View的初始值,View终止值
    private void performAimate(View target,int start,int end){
      //设置进度值,并获得对象
      ValueAnimator valueAnimator = ValueAnimator.ofInt(1,100);
      //添加监听器
      valueAnimator.addUpdateListener(new AnimatorUpadateListener(){
        //线性估值器
        priavte IntEvaluator mEvaluator = new IntEvaluator();
        
        @Override
        public void onAnimationUpdate(ValueAnimator value){
          //获取当前进度百分比  0~1
          float fraction = value.getAnimatedFraction();
          //设置比例,估值,设为宽度
          target.getLayoutParams.width = mEvaluator.get(fraction,start,end);
          //requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent view重新调用他的onMeasure onLayout来对重新设置自己位置。
          target.requsetLayout();
        }
      });
      //设置时常。并启动
      valueAnimator.setDurction(500).start();
    }
    
    public void onClick(View v){
        performAnimator(mButton,300,500);
    }
    View Code

    八、属性动画的原理

    工作原理:属性动画要求动画提供该属性的方法,属性动画根据传递的属性的初始值和最终值,多次调用set()方法。如果动画没有传递初始值,那么就还要提供get()方法,由系统去获取属性的初始值。

    源码分析:(P288~292)作用判断如果当前动画、等待动画、和延迟动画有和当前动画一致的时候,就把相同动画cancel了

  • 相关阅读:
    java线程学习之volatile关键字
    java线程学习之yield方法
    java线程学习之join方法
    小程序hideTarBar隐藏TabBar后,获取windowHeight不准确问题
    canvas等base64格式上传到服务端直传到oss
    服务器关于node的注意事项
    node.js连接本地数据库
    小程序(mpvue框架)的总结
    git代码的注意
    js里的实用小技巧
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5449012.html
Copyright © 2011-2022 走看看