您的位置:首页 > 移动开发 > Android开发

android动画 -- Property Animator

2015-10-19 23:27 615 查看
Property Animation就是通过设置动画的实际动作属性,完成动画效果;

和属性动画相关的类:

[code]ObjectAnimator  动画的执行类

ValueAnimator 动画的执行类

AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。

AnimatorInflater 用户加载属性动画的xml文件

TypeEvaluator  类型估值,主要用于设置动画操作属性的值。(我觉得就是模拟动画过程,实时从模拟过程中获取动画的状态值,位置/尺寸等,将这些属性设置到真正的动画里面去)
Time interpolation:时间差值,乍一看不知道是什么,但是我说LinearInterpolator、AccelerateDecelerateInterpolator;动画加载器定义动画的变化率


ObjectAnimator实现动画:

提供了ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。

动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法~

例子:

//设置图片旋转 以X轴为对称轴开始0度 最后360独

//第二个字符串表示: 调用setPropName去设置图片的属性 动画的过程实质就是不断的调用setter方法去设置变化的值

[code] public void onRotate(View v){
        ObjectAnimator.ofFloat(v, "rotationY", 0.0f, 180.0f).setDuration(1000).start();
    }


[code]多个动画效果添加一起执行有以下三种方法:


[code]//多个动作弄在一块  :  可以选择AnimatorSet或者如下添加刷新器
    public void onRotate(final View v){

        /*方法一:
        //设置多组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();     

        方法二
         setProperty的name随意取,我们最后通过后面的方法获取值就可以
         每一帧图像刷新的时候就调用下面的监控函数,在里面我们去设置那个值就可以了
        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();
    }


ValueAnimator实现动画

[code]单个动画动作使用方法:
在ValueAnimator定义好图形的动画过程,在显示图像刷图像帧的时候实时设置图像的位置,即实现了动画,下面以竖直运动为例:


[code]public void onVertical(View v){
        ValueAnimator animator = ValueAnimator.ofFloat(0,mHeight - image.getHeight());          //规定好起始和最终值,这是一个过程
        Log.i(TAG, "mHeight: " + mHeight + " image.getHeight(): " + image.getHeight());
        animator.setTarget(image);
        animator.setDuration(2000);
        animator.start();
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator arg0) {
                // TODO Auto-generated method stub
                image.setTranslationY((Float)arg0.getAnimatedValue());          //图像刷帧的时候实时获取值在设置即可
            }
        });
    }


[code]多个动作,由于比较复杂,可以使用一个模拟器模拟器过程:


[code]    public void onPaowu(View v){
        ValueAnimator animator = new ValueAnimator();
        animator.setObjectValues(new PointF(0,0));
        animator.setInterpolator(new LinearInterpolator());
        animator.setDuration(4000);
        animator.setEvaluator(new TypeEvaluator<PointF>() {
            //这其实是一个模拟运动过程  我们只是需要模拟过程中图像的属性值 在把值应用刷新到动画里面去即可
            @Override
            public PointF evaluate(float arg0, PointF startValue, PointF endValue) {
                // TODO Auto-generated method stub
                //参数1:当前位置参数
                //模拟抛物线运动   水平方向 vt  竖直方向:1/2  gt^2
                PointF p = new PointF();
                p.set(arg0 * 200 * 5, 0.5f * 200 * arg0 * arg0 * 7);

                return p;
            }

        });

        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator arg0) {
                // TODO Auto-generated method stub
                PointF p = (PointF)arg0.getAnimatedValue();
                image.setX(p.x);
                image.setY(p.y);
            }
        });

        animator.start();
    }


[code]如上,可以看出,设置一个模拟器,自己实时计算里面的值,将返回的值用于View的设置既可


动画监听事件:

即在动画在开始、中途和结束等状态时的事件操作;

[code]        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

            }
        });


[code]AnimatorListener是一个接口,所以每个方法都需要重写,如果只想写其中某一个或几个方法,可以使用AnimatorListenerAdapter,它是AnimatorListener的子类,但是是一个抽象类,每个方法都是空的


XML方式使用动画:

在res/anim下创建xml文件

[code]<?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();


布局动画(Layout Animator):

布局动画主要使用LayoutTransition类为布局容器设置动画,即容器中某一图像变化而引起整个容器里面的图像而变化的效果 – 过渡效果

LayoutTransition transition = new LayoutTransition();

transition.setAnimator(LayoutTransition.APPEARING,null);

[code]如上设置的过程代码,过渡的效果有四种:
LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画

LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画

LayoutTransition.DISAPPEARING  当一个View在ViewGroup中消失时,对此View设置的动画

LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画

LayoutTransition.CHANGE 不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画。


例子:

动态添加按钮,查看效果

[code]    private ViewGroup viewGroup;
    private GridLayout mGridLayout;
    private int mVal;
    private LayoutTransition mTransition;

    private CheckBox mAppear, mChangeAppear, mDisAppear, mChangeDisAppear;  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewGroup = (ViewGroup) this.findViewById(R.id.container);
        mAppear = (CheckBox) findViewById(R.id.id_appear);  
        mChangeAppear = (CheckBox) findViewById(R.id.id_change_appear);  
        mDisAppear = (CheckBox) findViewById(R.id.id_disappear);  
        mChangeDisAppear = (CheckBox) findViewById(R.id.id_change_disappear);

        mAppear.setOnCheckedChangeListener(this);  
        mChangeAppear.setOnCheckedChangeListener(this);  
        mDisAppear.setOnCheckedChangeListener(this);  
        mChangeDisAppear.setOnCheckedChangeListener(this);  

       // 创建一个GridLayout  
        mGridLayout = new GridLayout(this);  
        // 设置每列5个按钮  
        mGridLayout.setColumnCount(5);  
        // 添加到布局中  
        viewGroup.addView(mGridLayout);  
        //默认动画全部开启  
        mTransition = new LayoutTransition();  
        mGridLayout.setLayoutTransition(mTransition);  
    }

    @Override
    public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
        // TODO Auto-generated method stub
        mTransition = new LayoutTransition();

        mTransition.setAnimator(LayoutTransition.APPEARING, mAppear.isChecked() ? 
                mTransition.getAnimator(LayoutTransition.APPEARING) : null);

        mTransition  
        .setAnimator(  
                LayoutTransition.CHANGE_APPEARING,  
                (mChangeAppear.isChecked() ? mTransition  
                        .getAnimator(LayoutTransition.CHANGE_APPEARING)  
                        : null));  
        mTransition.setAnimator(  
                LayoutTransition.DISAPPEARING,  
                (mDisAppear.isChecked() ? mTransition  
                        .getAnimator(LayoutTransition.DISAPPEARING) : null));  
        mTransition.setAnimator(  
                LayoutTransition.CHANGE_DISAPPEARING,  
                (mChangeDisAppear.isChecked() ? mTransition  
                        .getAnimator(LayoutTransition.CHANGE_DISAPPEARING)  
                        : null));  

        mGridLayout.setLayoutTransition(mTransition);
    }

    public void addBtn(View view)  
    {  
        final Button button = new Button(this);  
        button.setText((++mVal) + "");  
        mGridLayout.addView(button, Math.min(1, mGridLayout.getChildCount()));  
        button.setOnClickListener(new OnClickListener()  
        {  

            @Override  
            public void onClick(View v)  
            {  
                mGridLayout.removeView(button);  
            }  
        });  
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: