android高级UI之补间动画和属性动画

1,365 阅读6分钟
原文链接: mp.weixin.qq.com

补间动画(Tween Animation)

补间动画是什么呢,简单通俗讲就是在res下建一个anim文件夹,里面放的动画文件所产生的动画叫补间动画.

这个补间动画动画值:

<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="60%p"
android:toYDelta="60%p"
android:fillAfter="true"//是否保存动画结束状态
android:duration="500">//动画执行的时间
</translate>

在代码中设置View执行动画

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tween_animation);
    mBtnStart = (Button) findViewById(R.id.btn_start);
    mBtnStart.setOnClickListener(new View.OnClickListener() {//设置点击事件
        @Override
        public void onClick(View v) {
            Toast.makeText(TweenAnimationActivity.this,"你点我干嘛哟?",Toast.LENGTH_SHORT).show();
        }
    });
    init();

}

  private void init() {
    Animation animation= AnimationUtils.loadAnimation(this,R.anim.translate);
    animation.start();
    mBtnStart.setAnimation(animation);
}

是不是很简单,这个Button就会执行平移动画了,最后显示在动画结束位置,在这里你点你看到的Button,点击事件是不是响应的,但是你点原来的位置,点击事件竟然响应了,竟然弹了 “”你点我干嘛哟?”””

下面对补间动画(Tween Animation)做了几点总结:
  • a. 补间动画(支持四种类型:平移(Translate)、旋转(Rotate)、缩放(Scale)、不透明度(Alpha)。

  • b. 只是显示的位置变动,View的实际位置未改变,表现为View移动到其他地方,点击事件仍在原处才能响应。(这个是重点,比如你设了控件点击事件,动画结束后,你点你看到的控件位置,是不会响应的,点原来的位置可以响应,这就是补间动画只是显示位置变动,实际位置没有改变)

  • c. 组合使用步骤较复杂。

  • d. View Animation 也是指此动画。

属性动画(Property Animation)

好了,这里我着重来讲一下属性动画,属性动画又是什么呢,其实属性动画就是真正改变了View的属性,View执行动画所在的位置,就是它实际所在的位置,简单来说就是以下几点:

  • a. 支持对所有View能更新的属性的动画(需要属性的setXxx()和getXxx())。

  • b. 更改的是View实际的属性,所以不会影响其在动画执行后所在位置的正常使用。

  • c. Android3.0 (API11)及以后出现的功能,3.0之前的版本可使用github第三方开源库nineoldandroids.jar进行支持。

    常用的几个API:
  • ObjectAnimator :对象动画执行类。

  • PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能。

  • AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。

  • Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值。

  • AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等。

  • TimeInterpolator :时间插值,用于控制动画执行过程。

  • ValueAnimator :值动画执行类,常配合AnimatorUpdateListener使用。

  • AnimatorUpdateListener :动画更新监听。

  • TypeEvaluator :类型估值,用于设置复杂的动画操作属性的值。

设置imageView向右平移100像素并设置随机透明度

         value +=100;
        mBtnStart.setTranslationX(value);//设置平移的位置
        mBtnStart.setAlpha((float) Math.random());//设置透明度

这也是设置imageView向右平移,这里还可以调置动画执行的时间

 ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(mBtnStart,"translationX",0f,(float)value);
    objectAnimator.setDuration(5000);//设置时间
    objectAnimator.start();

直接看下面的图吧,直观:

多个动画同时执行
方法一:

设置动画监听,开始第一个动画同时开启其他动画

ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(mBtnStart,"6666",0f,300f);
    objectAnimator.setDuration(3000);
   objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float animationAnimatedValue= (float) animation.getAnimatedValue();
           /* mBtnStart.setScaleX(0.5f+animationAnimatedValue/600f);
            mBtnStart.setScaleY(0.5f+animationAnimatedValue/600f);*/
           mBtnStart.setTranslationX(animationAnimatedValue);
            mBtnStart.setTranslationY(animationAnimatedValue);
        }
    });
    objectAnimator.start();

看了以上代码,发现是不是有点怪,怎么属性方法怎么会有"6666"这个,哈哈,其实是没有这个属性方法,但是,没有这个属性方法怎么会执行呢,深入源码分析的话,会发现没有这个属性时 ObjectAnimator就是Valueanimator,Valueanimator是没有属性的,所以动画还是会执行的.好了,看方法二用valueanimator;

方法二:

用Valueanimator监听动画执行过程,这样也可以达到同时执行动画的效果

    ValueAnimator animator = ValueAnimator.ofFloat(0f,200f);
    animator.setDuration(200);
    animator.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mBtnStart.setTranslationX(animationAnimatedValue);
            mBtnStart.setTranslationY(animationAnimatedValue);
        }
    });
    animator.start();
方法三:

用PropertyValuesHolder,组合动画这样也可以达到同时执行动画的效果

PropertyValuesHolder holder=PropertyValuesHolder.ofFloat("translationX",0,200,500);
    PropertyValuesHolder holder1=PropertyValuesHolder.ofFloat("translationY",0,300,500);
    ObjectAnimator objectAnimator =ObjectAnimator.ofPropertyValuesHolder(mBtnStart,holder,holder1);
    objectAnimator.setDuration(5000);
    objectAnimator.start();
方法四:

用AnimatorSet,真正的动画组合,直接看代码吧,很简单的;

     ObjectAnimator objectAnimator1=ObjectAnimator.ofFloat(mBtnStart,"translationX",0,200,500);
    ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(mBtnStart,"translationY",0,200,500);
    AnimatorSet animatorSet =new AnimatorSet();
    animatorSet.setDuration(5000);
    //animatorSet.playTogether(objectAnimator,objectAnimator1);//同时执行
   animatorSet.playSequentially(objectAnimator,objectAnimator1);//依次执行动画
    animatorSet.start();

用playTogether的话可以把一个个动画组合同时执行;而用playSequentially的话是把动画一个个组合然后依次一个个执行;

属性动画加速器(也叫插值器)

什么叫做属性动画加速器呢;

我们前面几个写的动画都是均速完成的,好像不是什么设置加速器,你想让你的动画开始那段不断加速执行,后面又慢慢减速执行,这个是怎么弄呢,这时属性动画加速器就得上场了;

 ObjectAnimator oa = ObjectAnimator.ofFloat(mBtnStart, "translationY", 0f,800f);
    oa.setDuration(5000);
    oa.setInterpolator(new AccelerateInterpolator(5));//设置加速器方法
    oa.start();

设置加速器方法就是setInterpolator(加速器名称);

以下就是加速器方法:

  • LinearInterpolator匀速前进(这个不多做解释,应该明白)

  • AccelerateDecelerateInterpolator 加速减速插值器 (先加速再减速)

  • AccelerateInterpolator 加速插值器(一直加速)

  • AnticipateInterpolator 回荡秋千插值器 (先回调一小步,然后加速前进)

  • AnticipateOvershootInterpolator (在上一个基础上超出终点一小步再回来加速前进,然后再减速)

  • BounceInterpolator 弹跳插值器(最后阶段弹跳效果,就是皮球打到地上的回弹效果)

  • CycleInterpolator 正弦周期变化插值器 (周期运动)

  • DecelerateInterpolator 减速插值器(减速)

  • OvershootInterpolator(快速到达终点并超过一小步最后再回来)

本人做android开发多年,以后会陆续更新关于android高级UI,NDK开发,性能优化等文章,更多请关注我的微信公众号:谢谢!