Android自定义控件开发入门与实战(5)KeyFrame和ViewPropertyAnimator

KeyFrame的ofFloat和ofInt
Keyframe除了ofFloat的方法,也有ofInt、ofObject这样的创建Keyframe实例的函数。
其构造函数都差不多。(fraction+value或者fraction)
可以通过 setFraction()和setValue来设置对应的进度和对应的值。

Keyframe的插值器
Keyframe可以让我们通过setInterpolator(TimeInterpolator interpolator)来设置一个插值器
如果给Keyframe设置插值器,那么,在从上一个Keyframe到当前Keyframe的中间值计算过程中,用的就是这个插值器。

Keyframe frame0= Keyframe.ofFloat(0f,0);
Keyframe frame1 = Keyframe.ofFloat(0.1f,-20);
frame1.setInterpolator(new BounceInterpolator());
Keyframe frame2 = Keyframe.ofFloat(1f,20);
frame2.setInterpolator(new LinearInterpolator());

在这里,从frame0到frame1用的是“弹性插值器”,而从frame1到frame2用的则是“线性插值器”

Keyframe的动画效果
(1)借助Keyframe产生一系列的 PropertyValuesHolder
(2) 通过ObjectAnimator.ofPropertyValuesHolder(view,frameholder1,frameHolder2,frameHolder3…)实现组合动画
所以通过Keyframe不用AnimatorSet就可以实现多动画同时播放。
这也是ObjectAnimator中唯一一个能够实现多动画同时播放的方法。(注:不是AnimatorSet)

ViewPropertyAnimator

这个机制Android3.1是为了让平时在使用属性动画时,会经常用到一些**常用属性(透明,位置。。)**而去做复杂的设计,为了让这个操作变得更加简洁而设计的。
比如在普通的,我们给TextView设置一个变透明的属性动画,如下:

ObjectAnimator anim = ObjectAnimator.ofFloat(textview,"alpha",0f);
anim.start();

而使用ViewPropertyAnimator则提供了更加浅显易懂的API,如下:

textview.animate().alpha(0);

就变成了一行简洁的代码了
再来看下面这个,将控件移动到(50,100)

view.animate().x(50).y(100);

它有3个注意的点

  1. animate():整个系统从调用View的这个animate()函数开始。
  2. 当这个动画被声明时,它就会被隐式的调用,是自动开始。
  3. 链式设置方法。每个接口方法都会返回一个ViewPropertyAnimator实例。

关于其别的API如下图所示:
在这里插入图片描述
其中对于像scaleX()、scaleY()等这些方法,还有其对应的 scaleXBy()… 它们的区别跟scrollTo和scrollBy的区别一样。
scaleXBy等带By的都是增量。
比如每次使用scaleX(2),目标view都是原来大小的两倍,而每次使用scaleXBy(2),增量放大两倍。

性能考量
(1)ViewPropertyAnimator并没有像ObjectAnimator一样使用反射或者JNI技术。
(2)它会根据每一个动画帧计算出对应的所有属性值,并设置给控件,然后调用一次invalidate()函数重绘,从而解决了在使用ObjectAnimator时每个属性都要单独计算单独重绘的问题。
(3)所以ViePropertyAnimator相对于ObjectAnimator和组合动画,性能有所提升。

并且在构造动画时会更加轻便。
但是ViewPropertyAnimator并不会取代属性动画。
ObjectAnimator更加的灵活、方便,可以作用在任何对象、属性上,而当需要对View的多个属性(SDK提供的,并非自定义的)进行操作时,ViewPropertyAnimator会更加便捷。

ViewGroup内的组件添加

我佛了…昨天敲了一个小时,最后忘记保存去跑步了,然后一个小时白敲了…QAQ…
Viewgroup动画就是对Viewgroup内部的子控件做动画效果。
比如一个listview在的每个item在每次进场、退场、添加、删除时使用的动画,上述的那些动画很难实现出来。
实现ViewGroup的动画有四个

  1. layoutAnimation标签和LayoutAnimationController
    API 1引入,子控件进场、退场都可以做动画,但是添加控件后,新的控件不能做出动画效果
  2. gridLayoutAnimation标签和GridLayoutAnimationController
    API 1引入,作用于GridView,优缺点和上述一样。
  3. android:animateLayoutChanges属性
    API 11引入,是解决上述两个动画的问题而出现的,可以在添加新控件后,新控件依然有动画,缺点是动画不能自定义。
  4. LayoutTransition
    API 11引入,解决上述的所有问题。

综上所述,LayoutTransition是最强的。
第三个 android:animateLayoutChanges设置为true时,可以带来动画,但是是系统默认的,如果我们想要实现自定义动画那就得使用LayoutTranstition。

LayoutTransition使用的三个步骤

  1. 创建实例
   LayoutTransition transition = new LayoutTransition();
  1. 创建动画并进行设置
        PropertyValuesHolder pivLeft = PropertyValuesHolder.ofInt("left",0,0);
        PropertyValuesHolder pivTop = PropertyValuesHolder.ofInt("top",0,0);
        PropertyValuesHolder pivScaleX = PropertyValuesHolder.ofFloat("scaleX",1f,0f,1f);
        Animator animator = ObjectAnimator.ofPropertyValuesHolder(ll,pivLeft,pivTop,pivScaleX);
        transition.setAnimator(LayoutTransition.CHANGE_APPEARING,animator);
  1. 将LayoutTransition添加到ViewGroup中
  ll.setLayoutTransition(transition);

然后设置监听事件

private void deleteView() {
        if (i > 0) {
            ll.removeViewAt(0);
        }
        i--;
    }

    private void addView() {
        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);
        ll.addView(button,0);
    }

就有下面的效果:
在这里插入图片描述
其中在setAnimator这一步中填入了参数,表示的是应用动画的对象范围:

  • APPEARING:元素在容器中出现时定义的动画
  • DISAPPEARING:元素在容器中消失时定义的动画
  • CHANGE_APPEARING:元素在添加新的元素时,其他需要变化的元素所应用的动画。
  • CHANGE_DISAPPEARING:容器某个元素消失时,其他需要变化的元素所应用的动画。

这些参数都比较好理解,一般最后两个我们平时很少用到,第一个第二个倒是会用到很多。

设置监听
LayoutTransition可以设置监听事件。

 transition.addTransitionListener(new LayoutTransition.TransitionListener() {
            @Override
            public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
            }

            @Override
            public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
            }
        });

上面四个参数分别是 LayoutTransition实例、ViewGrop父容器、View 当前所做动画的子控件、transitionType就是刚刚讲的那四个类型。

开源动画库NineOldAndroids

这是Android 3.0推出的全新的Animation API,使用起来很方便,但是不能再3.0一下版本中使用。NineOldAndroids是一个可以再任意Android版本上使用的AnimationAPI,和Android3.0中的API类似。
常用的有ObjectAnimator、ValueAnimator、AnimatorSet、PropertyValuesHolder、Keyframe、ViewPropertyAnimator和ViewHelper。

前面的那一堆都和Android 官方API是对应的,只是包名换成了 com.nineoldandroids.animation。ViewPropertyAnimator和官方API只有一点点出入。只有LayoutTransition只在官方API才有。

这里讲一下之前没有提到过的、NineOldAndoids提供的动画 ViewHelper。
ViewHelper
ViewHelper提供了一系列静态set/get函数去操作View的各种属性,就是透明度、偏移、旋转,而且已经兼容低版本。

public static float getAlpha(View v)
public startic void setAlpha(View view, float alpha)
.....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值