Android自定义控件——04属性动画补充

4.属性动画补充

4.1 PropertyValuesHolder与Keyframe

  • ValueAnimator和ObjecAnimator除可以通过oflnt()、ofFloat()、ofObject()函数创建实例外,还都有一个ofPropertyValuesHoIder()函数来创建实例。

4.1.1 PropertyValuesHolder

  • 创建PropertyValuesHolder实例的函数:

    public static PropertyValuesHolder ofFloat(String propertyName,float...values)
    public static PropertyValuesHolder ofint(String propertyName,int .. values)
    public static PropertyValuesHolder ofObject(String propertyName,TypeEvaluator evaluator,Object...values)
    public static PropertyValuesHolder ofKeyframe(String propertyName,Keyframe...values)
    
  • ObjecAnimator.ofPropertyValuesHolder():

    public static ObjecAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder...values)
    
  • PropertyValuesHolder之ofObject():

    public static PropertyValuesHolder ofObject(String propertyName,TypeEvaluator evaluator,Object...values)
    

4.1.2 Keyframe

  • 为了方便地控制动画速率的问题, Google定义了Keyframe 类。

    public static Keyframe ofFloat(float fraction , float value)
    
    • fraction:表示当前的显示进度, 即在插值器中getlnterpolation()函数的返回值。
    • value:表示动画当前所在的数值位置。
  • PropertyValuesHolder的ofKeyframe函数:

    public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe...values)
    
  • 其他函数:

    public void setFraction(float fraction)//设置fraction参数,即Keyframe所对应的进度
    public void setValue(Object value)//设置当前Keyframe所对应的值
    public void setinterpolator(Timeinterpolator interpolator)//设置差值器
        
    //PropertyValuesHolder的补充函数
    public void setEvaluator(TypeEvaluator evaluator)//设置动画的Evaluator
    public void setFloatValues(float...values)//用于设置ofFloat()所对应的动画值列表
    public void setintValues(int...values)//用于设置ofint()所对应的动画值列表
    public void setKeyframes(Keyframe ... values )//用于设置ofKeyframe()所对应的动画值列表
    public void setObjectValues(Object...values)//用于设置ofObject()所对应的动画值列表
    public void setPropertyName(String propertyName)//设置动画属性名
    

4.2 ViewPropertyAnimator

4.2.1 概述

  • 用法对比:

    //原用法
    ObjectAnimator animator = ObjectAnimator.ofFloat(textview,"alpha",0f);
    animator.start();
    
    //ViewPropertyAnimator提供的API
    textview.animate().alpha(0f);//透明度
    myView.animate().x(50).y(100);//平移
    
    • **animate():**系统从调用View 的animate()函数开始。该函数返回一个ViewPropertyAnimator对象,可通过调用这个对象的函数来设置需要实现动画的属性。
    • **自动开始:**不需显式调用过start()函数。
    • **流畅(Fluent):**允许将多个函数调用串在一起,并把一个多属性的动画写成一行代码。

4.2.2 常用函数

函数 含义
alpha(tloat value) 设置透明度
scaleY(tloat value) 设置Y轴方向的缩放大小
scaleX(tloat value) 设置X轴方向的缩放大小
translationY(tloat value) 设置Y轴方向的移动值
translationX(tloat value) 设置X轴方向的移动值
rotation(float value) 设置绕Z轴旋转度数
rotationX(float value) 设置绕X轴旋转度数
rotationY(float value) 设置绕Y轴旋转度数
x(float value) 相对于父容器的左上角坐标在X轴方向的最终位置
y(float value) 相对于父容器的左上角坐标在Y轴方向的最终位置
alphaBy(float value) 设置透明度增量
rotationBy(float value) 设置绕Z轴旋转增量
rotationXBy(float value) 设置绕X轴旋转增量
rotationYBy(float value) 设置绕Y轴旋转增量
translationXBy(float value) 设置X轴方向的移动值增量
translationYBy(float value) 设置Y轴方向的移动值增量
scaleXBy(float value) 设置X轴方向的缩放大小增量
scaleYBy(float value) 设置Y轴方向的缩放大小增量
xBy(float value) 相对于父容器的左上角坐标在X轴方向的位置增量
yBy(float value) 相对于父容器的左上角坐标在Y轴方向的位置增量
setlnterpolator(Timelnterpolator interpolator) 设置插值器
setStartDelay(long startDelay) 设置开始延时
setDuration(long duration) 设置动画时长

4.2.3 性能考量

  • ViewPropertyAnimator并没有像ObjectAnimator 一样使用反射或者JNI 技术;而ViewPropertyAnimator会根据预设的每一个动画帧计算出对应的所有属性值,并设置给控件,然后调用一次invalidate() 函数进行重绘,从而解决了在使用ObjectAnimator时每个属性单独计算、单独重绘的问题。所以ViewPropertyAnimator相对于 bjectAnimator和组合动画,性能有所提升
  • 使用ObjectAnimator时并不需要太过担心性能,使用反射和JNI 等技术所带来的开销相对于整个程序来讲都是微不足道的。使用ViewPropertyAnimator最大的优势不在于性能的提升,而是它提供的简明易读的代码书写方式

4.3 为ViewGroup内的组件添加动画

  • 方法一:layoutAnimation标签与LayoutAnimationController(有缺陷)
  • 方法二:gridlayoutAnimation 标签与GridlayoutAnimationController(有缺陷)
  • 方法三:android:animatelayoutChanges属’性(不能自定义动画)
  • 方法四:LayoutTransition(最强大)

4.3.1 animatelayoutChanges 属性

  • XML中定义:

    android:animateLayoutChanges="true”
    
  • 代码处理:

    //添加控件
    private void addButtonView(){
        i++;
    	Button button= new Button(this);
    	button.setText("button"+i) ;
    	LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
    	button.setLayoutParams(params);
    	linearLayoutContainer.addView(button,0);
    }
    //删除控件
    private void removeButtonView(){
        if(i > 0){
            linearLayoutContainer.removeViewAt(0);
        }
        i--;
    }
            
    

4.3.2 LayoutTransition

  • 创建实例:

    LayoutTransition transitioner = new LayoutTransition();
    
  • 创建动画并进行设置:

    ObjectAnimator animOut = ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f);
    transitioner.setAnimator(LayoutTransition.DISAPPEARING,animOut);
    //函数原型
    public void setAnimator(int transitionType,Animator animator)
    
    • APPEARING:元素在容器中出现时所定义的动画。
    • DISAPPEARING:元素在容器中消失时所定义的动画。
    • CHANGE_APPEARING:由于容器中要显现一个新的元素, 其他需要变化的元素所应用的动画。(不常用,可能存在问题)
    • CHANGE_DISAPPEARING : 当容器中某个元素消失时, 其他需要变化的元素所应用的动画。(不常用,可能存在问题)
  • 将LayoutTransition设置到ViewGroup中:

    linearLayout.setLayoutTransition(transitioner);
    
  • 注意:(针对CHANGE_APPEARING、CHANGE_DISAPPEARING)

    • LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须使用PropertyValuesHolder所构造的动画才会有效果。

    • 在构造PropertyValuesHolder动画时,“left”、“top”属性的变动是必写的。如果不需要变动,则直接写为:

      PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,0);
      PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);
      
    • 在构造PropertyValuesHolder动画时,所使用的ofInt()、ofFloat()函数中的参数值,第一个值和最后一个值必须相同:否则此属性所对应的动画将被放弃,在此属性值上将不会有效果。

      PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",1f,0f,1f);
      
    • 在构造PropertyValuesHolder动画时,所使用的oflnt()、ofFloat()函数中,如果所有参数值都相同,则将不会有动画效果。比如:

      PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",100f,100f);
      

4.3.3 其他函数

  • 基本设置:

    /**
    * 设置所有动画完成所需要的时长
    */
    public void setDuration(long duration)
    /**
    * 针对单个Type设置动画时长;
    * transitionType 取值为 APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING
    */
    public void setDuration(int transitionType,long duration)
    /**
    * 针对单个Type设置插值器
    */
    public void setInterpolator(int transitionType,TimeInterpolator interpolator)
    /**
    * 针对单个Type设置动画延时
    */
    public void setStartDelay(int transitionType,long delay)
    /**
    * 针对单个Type设置每个子item动画的时间间隔
    */
    public void setStagger(int transitionType,long duration)
    
  • 设置监听:

    public void addTransitionListener(TransitionListener listener)
    //其中:
    public interface TransitionListener{
        public void startTransition(LayoutTransition transition,ViewGroup container,
    View view,int transitionType);
        public void endTransition(LayoutTransition transition,ViewGroup container,View view,int transitionType);
    }
    
    • LayoutTransition transition :当前的LayoutTransition 实例。
    • ViewGroup container:当前应用LayoutTransition的容器。
    • View view:当前在做动画的View对象。
    • int transitionType:当前的LayoutTransition 类型,取值有 APPEARING、DISAPPEARING、CHANGE_APPEARING和CHANGE_DISAPPEARING。
  • 注意:

    • APPEARING/DISAPPEARING:事件针对当前被添加的控件做动画,所以返回的View 是当前被添加的控件
    • CHANGE_APPEARING/CHANGE_DISAPPEARING:事件针对容器中所有已经存在的控件做动画,所以返回的View是容器。

参考资料

  • 《Android自定义控件开发入门与实战》
发布了64 篇原创文章 · 获赞 65 · 访问量 8797

猜你喜欢

转载自blog.csdn.net/qq_33334951/article/details/103786790
今日推荐