android动画 -- Property Animator

属性动画原理

根据时间的推移,Property Animation改变组件view的实际动作属性,从而完成动画效果;在组件开始动画之前必须满足一个条件,就是必须要提供组件的setX和getX方法,因为属性动画会根据你传入的propertyName,如下“width”,它会去你的mButton里面去找setWidth方法,如果你的propertyName不对,它会包找不到setPropertName这个方法,无法完成动画;
但是如果你使用Button来做动画效果时,如下代码:

ObjectAnimator.ofInt(mButton, "width", 500).setDuration(5000).start(); 

发现它根本就没有动画效果,这是因为Button是继承TextView的,虽然提供了setWidth和getWidth方法,但是TextView的setWidth根本不是改变组件的宽度值,其源码如下:

@android.view.RemotableViewMethod
    public void setWidth(int pixels) {
        mMaxWidth = mMinWidth = pixels;
        mMaxWidthMode = mMinWidthMode = PIXELS;

        requestLayout();
        invalidate();
    }

所以,在我们使用一些组件的时候,如果动画效果不发生改变的话,建议对组件进行封装一下,执行提供set和get方法,如下方案:

private static class ViewWrapper{

        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();
        }
    }

        Button btn = (Button)findViewById(R.id.btn);
        final ViewWrapper wrapper = new ViewWrapper(btn);
        btn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                ObjectAnimator.ofInt(wrapper , "width", 500).setDuration(5000).start();
            }
        });

这样就能正确完成动画效果了;从上面也可以看出,属性动画就是在动画过程中改变组件的状态值,从而完成动画效果,下面讲讲动画的使用;

ObjectAnimator 动画的执行类

ObjectAnimator 可以直接作用在组件上,根据设置的动画的各个状态值完成动画,使用方法超级简单,看范例即可:

TextView tv = (TextView)findViewById(R.id.text);
ObjectAnimator.ofInt(tv, "width", 0, 500).setDuration(5000).start();
ObjectAnimator.ofInt(tv, "width", 0, 500).setDuration(5000).start();

注意第二个参数width,动画过程中它会去找setWidth,所以你必须填写对

ValueAnimator

ValueAnimator 不能直接作用在view组件上,它用于状态的模拟,也就是组件从一个状态变化到另一个状态,模拟出中间的每个状态值,组件再把这个状态值设置到自身上去,从而实现动画效果,看使用范例:

public void animatorTest(final View view){
        ValueAnimator animator = ValueAnimator.ofInt(view.getLayoutParams().width,view.getLayoutParams().width + 100);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator arg0) {
                // TODO Auto-generated method stub
                Integer i = (Integer)arg0.getAnimatedValue();
                Log.i("jackzhous", "i = " + i);
                view.getLayoutParams().width = i; 
                view.requestLayout();
            }
        });
        animator.setDuration(1000).start();
    }

设置监听,更新状态即可;

组合动画

组合动画也就是将上面几个动画加在一起一块执行;方法有三种

使用AnimatorSet

//设置多组ObjectAnimator对象动画效果;设置他们的动画先后关系*/
        ObjectAnimator anim1 =  ObjectAnimator.ofFloat(v, "scal", 1f, 0.0f).setDuration(1000);
         ObjectAnimator anim2 =  ObjectAnimator.ofFloat(v, "scaleY", 1f, 0.0f).setDuration(1000);
         ObjectAnimator anim3 =  ObjectAnimator.ofFloat(v, "alpha", 1f, 0.0f).setDuration(1000);
        AnimatorSet aS = new AnimatorSet();
        aS.play(anim1).with(anim2);
        aS.play(anim2).with(anim3);

        aS.start();  

使用ObjectAnimator 时,同时增加更新监听

每一帧图像刷新的时候就调用下面的监控函数,在里面我们去设置那个值就可以了
        ObjectAnimator anim =  ObjectAnimator.ofFloat(v, "scal", 1f, 0.0f).setDuration(1000);
        anim.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator arg0) {
                // TODO Auto-generated method stub
                float value = (Float) arg0.getAnimatedValue();
                v.setAlpha(value);
                v.setScaleX(value);
                v.setScaleY(value);
                Log.i(TAG, "onAnimationUpdate");
            }
        });
        anim.start();

通过PropertyValuesHolder设置动画属性,将属性添加到ObjectAnimator里面去即可

        PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 0.0f, 1.0f);
        PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 0.0f, 1.0f);
        PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f);
        ObjectAnimator.ofPropertyValuesHolder(v, holder1, holder2, holder3).setDuration(5000).start();
    }

动画监听

有时候我们需要监听动画过程的每个状态,从而执行相应的动作,属性动画为我们提供了监听,

animator.addListener(new AnimatorListener() {

            @Override
            public void onAnimationStart(Animator arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationRepeat(Animator arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationEnd(Animator arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationCancel(Animator arg0) {
                // TODO Auto-generated method stub

            }
        });

XML方式使用动画:

在res/anim下创建xml文件 
<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:ordering="together" >  

    <objectAnimator  
        android:duration="1000"  
        android:propertyName="scaleX"  
        android:valueFrom="1"  
        android:valueTo="0.5" >  
    </objectAnimator>  
    <objectAnimator  
        android:duration="1000"  
        android:propertyName="scaleY"  
        android:valueFrom="1"  
        android:valueTo="0.5" >  
    </objectAnimator>  

</set>  
    Java代码中读取:
      Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);    //利用AnimatorInflater读取xml文件
        mMv.setPivotX(0);  
        mMv.setPivotY(0);  
        //显示的调用invalidate  
        mMv.invalidate();  
        anim.setTarget(mMv);        //设置对象
        anim.start();
posted @   帅气好男人_jack  阅读(7)  评论(0编辑  收藏  举报  
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示