Property Animation属性动画

动画类型

  • View Animation(Tween Animation 补间动画)
    只能支持简单的缩放、平移、旋转、透明度等基本的动画,且有一定的局限性
    动画时View的真正的View的属性保持不变,实际位置未改变
    原理:提供动画的起始和结束状态信息,中间的状态根据上述类里差值器算法填充
  • Drawable Animation(Frame Animation 帧动画)
  • Property Animation(属性动画)
    它更改的是对象的实际属性,

Property Animation属性

  • Duration:动画的持续时间
  • TimeInterpolation:属性值的计算方式,如先快后慢
  • TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
  • Repeat Count and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
  • Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响

Property Animation 动画流程

ValueAnimator

ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:

  1. 计算属性值
  2. 根据属性值执行相应的动作,如改变对象的某一属性。(需要在onAnimationUpdate中传入执行动画的对象)
/**
     * 自由落体
     * @param view
     */
        ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight
                - mBlueBall.getHeight());
        animator.setTarget(mBlueBall);
        animator.setDuration(1000).start();
//        animator.setInterpolator(new CycleInterpolator(3));
        animator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
            // //这个函数中会传入ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值
                mBlueBall.setTranslationY((Float) animation.getAnimatedValue());
        
            }
        });
    }

    /**
     * 抛物线
     * @param view
     */
    public void paowuxian(View view)
    {

        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setDuration(3000);
        valueAnimator.setObjectValues(new PointF(0, 0));
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>()
        {
            // fraction = t / duration
            @Override
            public PointF evaluate(float fraction, PointF startValue,
                    PointF endValue)
            {
                Log.e(TAG, fraction * 3 + "");
                // x方向200px/s ,则y方向0.5 * 10 * t
                PointF point = new PointF();
                point.x = 200 * fraction * 3;
                point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3);
                return point;
            }
        });

        valueAnimator.start();
        valueAnimator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                PointF point = (PointF) animation.getAnimatedValue();
                mBlueBall.setX(point.x);
                mBlueBall.setY(point.y);

            }
        });
    }

ObjectAnimator

ObjectAnimator继承自ValueAnimator,要指定一个对象及该对象的一个属性,例如

  • 常用方法有ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()。
  • 属性动画可用的属性
    答案是:任何一切带有set开头的方法属性名字。可能我们常用的有:
  • 平移 translationX,translationY, X,Y。
  • 缩放 scaleX,scaleY。
  • 旋转 rotationX, rotationY。
  • 透明度 alpha。

也就是说我们所有控件都有以上setTranslationX(),setScaleX(),setRotationX(),setAlpha()等方法。
我们不仅限于这几个属性,就拿TextView控件来说,只要是TextView有的属性都可以用来实现动画效果,比如 字体大小:“textColor”,字体颜色“textSize”等。

限制:对象应该有一个setter函数:set<PropertyName>(驼峰命名法)及要有相应属性的getter方法:get<PropertyName>
且应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。

 ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, 'alpha', 1.0f, 0.3f, 1.0F);
        animator.setDuration(2000);//动画时间
        animator.setInterpolator(new BounceInterpolator());//动画插值
        animator.setRepeatCount(-1);//设置动画重复次数
        animator.setRepeatMode(ValueAnimator.RESTART);//动画重复模式
        animator.setStartDelay(1000);//动画延时执行
        animator.start();//启动动画
                        ```
> 根据应用动画的对象或属性的不同,如果内部没有调用view的重绘,可能需要在onAnimationUpdate函数中调用invalidate()函数刷新视图。

###组合动画
 - **组合动画1–AnimatorSet的使用**
这个类提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:
   - after(Animator anim) 将现有动画插入到传入的动画之后执行
   - after(long delay) 将现有动画延迟指定毫秒后执行
   - before(Animator anim) 将现有动画插入到传入的动画之前执行
   - with(Animator anim) 将现有动画和传入的动画同时执行
   
   > Android 除了提供play(),还有playSequentially(),playTogether() 可供使用,可传入一个或者多个动画对象(,隔开),或者动画集合
   

ObjectAnimator animator = ObjectAnimator.ofInt(container, "backgroundColor", 0xFFFF0000, 0xFFFF00FF);
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 0.0f, 200.0f, 0f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 2.0f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "rotationX", 0.0f, 90.0f, 0.0F);
ObjectAnimator animator4 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.2f, 1.0F);

            //组合动画方式1
            AnimatorSet set = new AnimatorSet();
           ((set.play(animator).with(animator1).before(animator2)).before(animator3)).after(animator4);
            set.setDuration(5000);
            set.start();
            ```
  • 组合动画2–PropertyValuesHolder的使用
    使用方法ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);第一个参数是动画的目标对象,之后的参数是PropertyValuesHolder类的实例,可以有多个这样的实例。代码如下:
PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("translationX", 0.0f, 300.0f);
                PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);
                PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 90.0f, 0.0F);
                PropertyValuesHolder valuesHolder3 = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.3f, 1.0F);

                ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, valuesHolder, valuesHolder1, valuesHolder2, valuesHolder3);
                objectAnimator.setDuration(2000).start();
                //类似于AnimatorSet.playTogether(Animator... items);
                ```
- **组合动画3-ViewPropertyAnimator(多属性动画)**
    // need API12

ViewPropertyAnimator animator=mBlueBall.animate()
.alpha(0)
.y(mScreenHeight / 2).setDuration(1000)
// need API 12
.withStartAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "START");
}
// need API 16
}).withEndAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "END");
runOnUiThread(new Runnable()
{
@Override
public void run()
{
mBlueBall.setY(0);
mBlueBall.setAlpha(1.0f);
}
});
}
}).start();
}

> 注意:使用ViewPropertyAnimator类需要API>=12

### 动画监听
- animator.addListener(new Animator.AnimatorListener(){});//监听动画开始,结束,取消,重复(四种都包括)
- animator.addListener(new  AnimatorListenerAdapter(){});
推荐,可代替AnimatorListener,需要监听动画开始,结束,取消,重复那种就直接实现那种方法就行
其实AnimatorListenerAdapter的源码只是一个实现了AnimatorListener接口的抽象类而已
- animator.addUpdateListener(new  ValueAnimator.AnimatorUpdateListener(){}); 
更加精确的方法来时刻监听当前动画的执行情况,可以读取到动画的每个更新值了

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
//可以根据自己的需要来获取动画更新值。
Log.e('TAG', 'the animation value is ' + value);
}
});


###Keyframes 
keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如以下例子:

/*

  • 动画效果:btn对象的width属性值使其:
  • 开始时 Width=400
  • 动画开始1/4时 Width=200
  • 动画开始1/2时 Width=400
  • 动画开始3/4时 Width=100
  • 动画结束时 Width=500
    */
    Keyframe kf0 = Keyframe.ofInt(0, 400);
    Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
    Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
    Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
    Keyframe kf3 = Keyframe.ofInt(1f, 500);
    PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
    ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
    rotationAnim.setDuration(2000);
### Property Animation在XML中使用
- xml文件放在res/animator/中

<set xmlns:android='http://schemas.android.com/apk/res/android'
android:duration='2000'
android:ordering='sequentially'>

<objectAnimator
    android:propertyName='translationX'
    android:valueFrom='0'
    android:valueTo='200'
    android:valueType='floatType' />

<set android:ordering='together'>
    <objectAnimator
        android:propertyName='scaleX'
        android:valueFrom='1'
        android:valueTo='2'
        android:valueType='floatType' />
    <objectAnimator
        android:propertyName='rotationX'
        android:valueFrom='0'
        android:valueTo='90'
        android:valueType='floatType' /><!--动画值的类型-->

</set>
- 通过AnimatorInflater.loadAnimator方法加载xml动画返回一个Animator的对象,然后调用setTarget方法给动画设置对象调用哪个start启动动画即可完成xml动画效果

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view);
animator.start();



###LayoutAnimation  布局动画
- LayoutTransition为布局的容器设置动画,当容器中的视图层次发生变化时存在过渡的动画效果。
- 过渡类型:
 - 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**设置的动画。

- 步骤:
 1. 实例化一个LayoutTransition对象
 3. 使用setAnimator 设置LayoutTransition对象的动画,这个动画包含了上述四个类型。可以使用android自带的动画,也可以使用自定义动画。本例中的自定义动画效果和上例一样。
  2. setLayoutTransition指定container的LayoutTransition对象
LayoutTransition transition = new LayoutTransition();
    transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
            transition.getAnimator(LayoutTransition.CHANGE_APPEARING));
    transition.setAnimator(LayoutTransition.APPEARING,
            null);
    transition.setAnimator(LayoutTransition.APPEARING, (mAppear
            .isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 1, 0): null));//可用使用自定义动画
    transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
            null);
    mGridLayout.setLayoutTransition(transition);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容