欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Android自定义view教程03---Android 属性动画 详解

来源: 开发者 投稿于  被查看 21083 次 评论:151

Android自定义view教程03---Android 属性动画 详解


1 package com.example.donghuatest;
 2 
 3 import android.animation.ObjectAnimator;
 4 import android.animation.PropertyValuesHolder;
 5 import android.animation.ValueAnimator;
 6 import android.animation.ValueAnimator.AnimatorUpdateListener;
 7 import android.app.Activity;
 8 import android.os.Bundle;
 9 import android.view.View;
10 import android.widget.ImageView;
11 
12 public class MainActivity extends Activity {
13 
14     // 比较简单的属性动画
15     private ObjectAnimator alphaAnimation = new ObjectAnimator();
16 
17     private ImageView imageView;
18 
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.activity_main);
23 
24         imageView = (ImageView) this.findViewById(R.id.iv);
25         imageView.setOnClickListener(new View.OnClickListener() {
26 
27             @Override
28             public void onClick(final View v) {
29                 rotateyAnimRunFirst(v);
30                 // rotateyAnimRunSecond(v);
31                 // rotateyAnimRunThird(v);
32             }
33         });
34 
35     }
36 
37     /**
38      * 横向翻转 Y轴不变
39      * 
40      * @param view
41      */
42     public void rotateyAnimRunFirst(final View view) {
43         ObjectAnimator anim = ObjectAnimator.ofFloat(view, "rotationY", 0.0F,
44                 360.0F).setDuration(500);
45         anim.start();
46     }
47 
48     /**
49      * 让这个图片由大变小 并且透明度也有变化 注意这个透明度变化到0的时候就结束了 并没有回复到初始状态
50      * 
51      * @param view
52      */
53     public void rotateyAnimRunSecond(final View view) {
54         ObjectAnimator anim = ObjectAnimator.ofFloat(view, "zhy", 1.0F, 0.0F)
55                 .setDuration(500);
56         anim.start();
57         anim.addUpdateListener(new AnimatorUpdateListener() {
58             @Override
59             public void onAnimationUpdate(ValueAnimator animation) {
60                 float cVal = (Float) animation.getAnimatedValue();
61                 view.setAlpha(cVal);
62                 view.setScaleX(cVal);
63                 view.setScaleY(cVal);
64             }
65         });
66 
67     }
68 
69     /**
70      * 另外一种一个动画 包含多种效果的方法 也更加方便 和第二个相比 他最终的结果仍是初始化的结果
71      * 
72      * @param view
73      */
74     public void rotateyAnimRunThird(final View view) {
75         PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
76                 0f, 1f);
77         PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
78                 0, 1f);
79         PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
80                 0, 1f);
81         ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ)
82                 .setDuration(1000).start();
83 
84     }
85 
86 }
 
 
 
这是写的一个属性动画的小demo,大家可以跑起来运行一下,总共有3个效果。
 
rotateyAnimRunFirst 这个函数 其实主要就是一个翻转的效果。
 
rotateyAnimRunSecond 这个函数 就是把图片从大到小变化一次 ,并且透明度也有变化。 相当于是一个混合的动画效果
 
rotateyAnimRunThird 这个函数和上面第二个函数效果其实差不多,只不过 这个到最后会回复到一开始的效果,并且用的方法也不一样。
 
 
 
其实这个属性动画,也是很好理解的,相对于其他两种动画来说,属性动画更改的是view 本身。
rotateyAnimRunFirst 这个函数 里面可以看到 传进去了
rotationY 这个值,到这里很多人就要问,这个地方的值要传什么,其实这个地方很好理解。对于第一种函数的 调用方式来说
 
你传什么值,这个属性动画就更改什么值,当然前提是这个值的 get set方法 必须有。
 
你如果传的值 没有get set方法的话 那这个属性动画 肯定是不起作用的。
 
比如我们这里的代码是更改的imageview 我们可以看一下 imageview 继承自 view
 
而view里面 是有这些get set方法的
 
 
 1  float mRotationY = 0f;
 2 
 3         /**
 4          * The degrees rotation around the horizontal axis through the pivot point.
 5          */
 6         @ViewDebug.ExportedProperty
 7         float mRotationX = 0f;
 8 
 9         /**
10          * The degrees rotation around the pivot point.
11          */
12         @ViewDebug.ExportedProperty
13         float mRotation = 0f;
14 
15         /**
16          * The amount of translation of the object away from its left property (post-layout).
17          */
18         @ViewDebug.ExportedProperty
19         float mTranslationX = 0f;
20 
21         /**
 
 
 
 
 
 
    /**
     * The degrees that the view is rotated around the vertical axis through the pivot point.
     *
     * @see #getPivotX()
     * @see #getPivotY()
     * @see #setRotationY(float) 
     * 
     * @return The degrees of Y rotation.
     */
    public float getRotationY() {
        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
    }
 
 
 
所以我们的first函数 是肯定可以执行成功的。
 
然后我们来看second函数。
 
 
anim.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(cVal);
                view.setScaleX(cVal);
                view.setScaleY(cVal);
            }
        });
 
 
 
着重看这里,其实也就猜到了,对于第二种函数的属性动画调用来说, 我们是自己去控制的。
 
  float cVal = (Float) animation.getAnimatedValue();
                view.setAlpha(cVal);
                view.setScaleX(cVal);
                view.setScaleY(cVal);
 
这边取得值以后 就自己更改v的属性了~~~很容易理解。
 
 
所以实际上这里的代码 还可以这么写
 
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "tttt", 1.0F, 0.0F)
.setDuration(500);
 
 
那个tttt 还可以改成你任意想改的名字 对结果没有影响,因为最终是我们手动用回调函数去更改view
的属性的,这个过程是我们自己写的,所以这里名字可以随便写,而first函数 则不可以 因为是
系统自己通过反射去调用set get方法的,所以传值的时候要注意~~
 
 
最后一个函数 third函数 其实就是把系统里面自己实现的过程给单拿出来 罢了 不信我们可以跟踪源代码
 
ObjectAnimator 里的这个函数
 
 
/**
     * Constructs and returns an ObjectAnimator that animates between float values. A single
     * value implies that that value is the one being animated to. Two values imply a starting
     * and ending values. More than two values imply a starting value, values to animate through
     * along the way, and an ending value (these values will be distributed evenly across
     * the duration of the animation).
     *
     * @param target The object whose property is to be animated. This object should
     * have a public method on it called <code>setName()</code>, where <code>name</code> is
     * the value of the <code>propertyName</code> parameter.
     * @param propertyName The name of the property being animated.
     * @param values A set of values that the animation will animate between over time.
     * @return An ObjectAnimator object that is set up to animate between the given values.
     */
    public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
        anim.setFloatValues(values);
        return anim;
    }
 
 
 
然后继续跟。
 
 /**
     * Sets the values, per property, being animated between. This function is called internally
     * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can
     * be constructed without values and this method can be called to set the values manually
     * instead.
     *
     * @param values The set of values, per property, being animated between.
     */
    public void setValues(PropertyValuesHolder... values) {
        int numValues = values.length;
        mValues = values;
        mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
        for (int i = 0; i < numValues; ++i) {
            PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
        }
        // New property/values/target should cause re-initialization prior to starting
        mInitialized = false;
    }
 
  @Override
    public void setFloatValues(float... values) {
        if (mValues == null || mValues.length == 0) {
            // No values yet - this animator is being constructed piecemeal. Init the values with
            // whatever the current propertyName is
            if (mProperty != null) {
                setValues(PropertyValuesHolder.ofFloat(mProperty, values));
            } else {
                setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
            }
        } else {
            super.setFloatValues(values);
        }
    }
 
 
然后我们third函数里面调用的方法
 
ofPropertyValuesHolder
 
 
 /**
     * Constructs and returns an ObjectAnimator that animates between the sets of values specified
     * in <code>PropertyValueHolder</code> objects. This variant should be used when animating
     * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows
     * you to associate a set of animation values with a property name.
     *
     * @param target The object whose property is to be animated. Depending on how the
     * PropertyValuesObjects were constructed, the target object should either have the {@link
     * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the
     * PropertyValuesHOlder objects were created with property names) the target object should have
     * public methods on it called <code>setName()</code>, where <code>name</code> is the name of
     * the property passed in as the <code>propertyName</code> parameter for each of the
     * PropertyValuesHolder objects.
     * @param values A set of PropertyValuesHolder objects whose values will be animated between
     * over time.
     * @return An ObjectAnimator object that is set up to animate between the given values.
     */
    public static ObjectAnimator ofPropertyValuesHolder(Object target,
            PropertyValuesHolder... values) {
        ObjectAnimator anim = new ObjectAnimator();
        anim.mTarget = target;
        anim.setValues(values);
        return anim;
 
最终也是通过 setValues 这个方法来做的。

用户评论