不积跬步无以至千里
伟大的成功都是靠着点滴 ~~~~ 我自己说的
开始整体 android 动画这个东西以前看过N次。用不了多久就忘记了。每次在做都要从新百度。然后摘取自己需要的。为了以后装大佬。我要从头再来 。
记得刚开始写代码的时候, 公司让我写个动画。图找不到了。 反正的效果就是背景是一个小马路。 你控制小汽车在那些马路上移动。我的神。 这怎么写。 我就憋呀憋,最后用线程。每隔一秒重汇一次、这种奇葩的招式。 我都佩服我自己。 现在想想不禁莞尔。 但是这么多年过去了。貌似我这方面没进展。 来吧。程序源们。大家开始GO
1 先来记住几个单词 代表的含义
alpha
渐变透明度动画效果
scale
渐变尺寸伸缩动画效果
translate
画面转换位置移动动画效果
rotate
画面转移旋转动画效果
动画的分类
View Animation(视图动画)
帧动画(Frame) :将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放
特点:帧动画 由于是一帧一帧的,所以需要图片多。会增大apk的大小,但是这种动画可以实现一些比较难的效果
比如说等待的环形进度
补间动画(Tween) 慢慢过渡,设置初值和末值,并用插值器来控制过渡
特点:相对也比较简单,页面切换的动画多用这个来做。缺点,视觉上
上变化,并不是真正的位置上的变化。
Property Animator(属性动画);
属性动画(Property) 控制属性来实现动画。
特点:最为强大的动画,弥补了补间动画的缺点,实现位置+视觉的变化。并且可以自定义插值器,实现各种效果
2动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式
这些名字说真的我总是混淆。没办法了找办法去记住、
先来scal
[skeɪl] (cal 呼叫 照死了呼叫你 让你给我测距离。 所以这个就是尺寸一直在变化的动画)
规模; 比例(尺); 鱼鳞; 级别;
测量; 攀登; 刮去…的鳞片;
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator= "@android:anim/accelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="2"
android:fromYScale="1.0"
android:toYScale="2"
android:pivotX="500"
android:pivotY="500"
android:fillAfter="true"
android:duration="1000" />
<!--
fromXScale 属性为动画起始时 X坐标上的伸缩尺寸
toXScale 属性为动画结束时 X坐标上的伸缩尺寸
fromYScale 属性为动画起始时Y坐标上的伸缩尺寸
toYScale 属性为动画结束时Y坐标上的伸缩尺寸
说明:
以上四种属性值
0.0表示收缩到没有
1.0表示正常无伸缩
值小于1.0表示收缩
值大于1.0表示放大
fillAfter 很重要代表动画结束后是不是要复位 当这个是false的时候 那么他就会返回中心了。
accelerate_interpolator 减速器(看动画的度速度)
android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
android:repeatCount 重复次数
android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
android:interpolator 设定插值器,其实就是指定的动作效果
-->
public class MainActivity extends Activity implements View.OnClickListener{
TextView ID1 ;
Button bt_1;
Animation a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt_1 = findViewById(R.id.bt_1);
bt_1.setOnClickListener(this);
a = AnimationUtils.loadAnimation(this,R.anim.scal);
ID1 = findViewById(R.id.id1);
ID1.startAnimation(a);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bt_1:
ID1.setVisibility(View.VISIBLE);
ID1.startAnimation(a);
break;
}
}
}
android:pivotX="50%p"
android:pivotY="50%p"
强烈说一些这两个的属性。 数值、百分数、百分数p 。 这个属性的是你要移动到的位置。如果没有这个属性。scale也就谈不上了。 没有他 我们上面的效果可以说 就是一个放大的过程。无非就是比例的问题。从0到几倍。 有了他 才叫做移动。 这些数值怎么算,就是从我们想要移动的左上角开始算 数值就是我们要移动的。 %就是你这个空间的单位50%就是代表你要移动你这个控件大小的长宽高。加上P 你可以理解成 parent 父亲。 父类 就是在他外面的控件的大小
贴几张大神弄得图
他的博客地址
http://blog.csdn.net/harvic880925/article/details/39996643 很详细。
android:fillAfter 上面看到的设置true就会不恢复 变成动画最后的状态
android:fillBefore android:fillEnabled
这两个一样都是恢复成之前的状态。 但是个人觉得没用。android:fillAfter 设置false就可以了。(理解错了。欢迎大神指点)
2alpha 意思 透明度。 (怎么记看到ph了。初中高中学过化学吧。ph试纸玩过吧。颜色的变化。透明度的变化 逐渐的透明。或者开始显示颜色等)
android:fromAlpha 动画开始的透明度,从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
android:toAlpha 动画结束时的透明度,也是从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="3000"
android:fillBefore="true">
</alpha>
上面位移尺寸懂了 这个就更好理解了 我就不多说了。
3 rotate 旋转(记忆方法 看a e 是不是一个旋转180的样子 ~ ~ )
android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度
android:pivotX="50%"
android:pivotY="50%"
还是想着重述说这个 scale 是移动的。这个是旋转。 怎么理解呢? 就是中心点的理解, 这个点。 还是左上角。50%就是重点。 上面gif图是90% 这样看就理解了吧。
ranslate标签 —— 平移
android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式
android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p
android:toXDelta 结束点X轴坐标
android:toYDelta 结束点Y轴坐标
这个理解稍微说一下 0 就是指的是左上角的坐标 来看一个gif
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="80%"
android:toXDelta="-80"
android:fromYDelta="80%"
android:toYDelta="-80"
android:duration="2000"
android:fillBefore="true">
</translate>
可以理解到吗?
还有一个综合的 set
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillAfter="true">
<translate
android:fromXDelta="80%"
android:toXDelta="-80"
android:fromYDelta="80%"
android:toYDelta="-80"
android:duration="2000"
android:fillBefore="true">
</translate>
<rotate
android:fromDegrees="0"
android:toDegrees="-650"
android:pivotX="90%"
android:pivotY="90%"
android:duration="3000"
android:fillAfter="true">
</rotate>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator= "@android:anim/accelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="2"
android:fromYScale="1.0"
android:toYScale="2"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="1000" />
</set>
这就是一个综合的效果。
二 Interpolator插值器 最让我挠头的地方 完全记不住。
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator= "@android:anim/anticipate_interpolator"
android:fromXScale="1.0"
android:toXScale="2"
android:fromYScale="1.0"
android:toYScale="2"
android:pivotX="50%p"
android:pivotY="50%p"
android:duration="1000"
android:fillAfter="true"
/>
先来记住几个单词
Accelerate 加速
Decelerate 减速
Interpolator 插补器
Anticipate 预见;预料;预感;先于…行动
Bounce 反弹
AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置
下面来分别看图。 为了方便 属性
android:fillAfter="true" 返回最后的位置
前两个不解释了 很好理解
主要看一下
android:interpolator= "@android:anim/anticipate_overshoot_interpolator"
很明显看到一个回头的动作
android:interpolator= "@android:anim/anticipate_interpolator"
没有那个动作 就是直接后撤然后向前废除
bounce_interpolator
反弹效果 很好理解 就不上图了
android:interpolator= "@android:anim/cycle_interpolator"
传说中的正玄定理
android:interpolator= "@android:anim/decelerate_interpolator"
先快后慢
android:interpolator= "@android:anim/linear_interpolator"
匀速
android:interpolator= "@android:anim/overshoot_interpolator"
可以理解成运动的距离超过预期的然后返回。 和之前有一个很像 区别就是没有一个后退(可以理解助跑)的一个概念
分析这么多。 这个东西主要还是对平移有很大关系 其他的影响不是特别大
这几种动画 都是通过xml 。 下面就要通过在代码中使用这些
二、Animation公共类
android:duration setDuration(long) 动画持续时间,以毫秒为单位
android:fillAfter setFillAfter(boolean) 如果设置为true,控件动画结束时,将保持动画最后时的状态
android:fillBefore setFillBefore(boolean) 如果设置为true,控件动画结束时,还原到开始动画前的状态
android:fillEnabled setFillEnabled(boolean) 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
android:repeatCount setRepeatCount(int) 重复次数
android:repeatMode setRepeatMode(int) 重复类型,有reverse和restart两个值,取值为RESTART或 REVERSE,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
android:interpolator setInterpolator(Interpolator) 设定插值器,其实就是指定的动作效果,比如弹跳效果等
上面学习 的都是补间动画
下面开始看属性动画Property Animator包括ValueAnimator和ObjectAnimation;
下面不同点还是摘自
http://blog.csdn.net/harvic880925/article/details/50525521
首先,直观上,他们有如下三点不同:
1、引入时间不同:View Animation是API Level 1就引入的。Property Animation是API Level 11引入的,即Android 3.0才开始有Property Animation相关的API。
2、所在包名不同:View Animation在包android.view.animation中。而Property Animation API在包 android.animation中。
3、动画类的命名不同:View Animation中动画类取名都叫XXXXAnimation,而在Property Animator中动画类的取名则叫XXXXAnimator
1、为什么引入Property Animator(属性动画)
我提出一个假设:请问大家,如何利用补间动画来将一个控件的背景色在一分钟内从绿色变为红色?这个效果想必没办法仅仅通过改变控件的渐入渐出、移动、旋转和缩放来实现吧,而这个效果是可以通过Property Animator完美实现的
这就是第一个原因:Property Animator能实现补间动画无法实现的功能
大家都知道,补间动画和逐帧动画统称为View Animation,也就是说这两个动画只能对派生自View的控件实例起作用;而Property Animator则不同,从名字中可以看出属性动画,应该是作用于控件属性的!正因为属性动画能够只针对控件的某一个属性来做动画,所以也就造就了他能单独改变控件的某一个属性的值!比如颜色!这就是Property Animator能实现补间动画无法实现的功能的最重要原因。
我们得到了第二点不同:View Animation仅能对指定的控件做动画,而Property Animator是通过改变控件某一属性值来做动画的。
假设我们将一个按钮从左上角利用补间动画将其移动到右下角,在移动过程中和移动后,这个按钮都是不会响应点击事件的。这是为什么呢?因为补间动画仅仅转变的是控件的显示位置而已,并没有改变控件本身的值。View Animation的动画实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,这样虽然View的大小或旋转角度等改变了,但View的实际属性没变,所以有效区域还是应用动画之前的区域;我们看到的效果仅仅是系统作用在按钮上的显示效果,利用动画把按钮从原来的位置移到了右下角,但按钮内部的任何值是没有变化的,所以按钮所捕捉的点击区域仍是原来的点击区域。(下面会举例来说明这个问题)
这就得到了第三点不同:补间动画虽能对控件做动画,但并没有改变控件内部的属性值。而Property Animator则是恰恰相反,Property Animator是通过改变控件内部的属性值来达到动画效果的
属性动画是控件的属性的变化。比如一个控件移动了 你点击监听,移动之后的位置你点击也可以响应。 视图动画就不可以。
二、ValueAnimator简单使用
第一步:创建ValueAnimator实例
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.setDuration(1000);
animator.start();
在这里我们利用ValueAnimator.ofInt创建了一个值从0到400的动画,动画时长是1s,然后让动画开始。从这段代码中可以看出,ValueAnimator没有跟任何的控件相关联,那也正好说明ValueAnimator只是对值做动画运算,而不是针对控件的,我们需要监听ValueAnimator的动画过程来自己对控件做操作
ValueAnimator animator = ValueAnimator.ofInt(0,400);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
这个方法就是活的运动点的值
tv.layout(curValue,curValue,curValue+tv.getWidth(),curValue+tv.getHeight());
}
});
animator.start();
setRepeatCount()、setRepeatMode()、cancel()
setRepeatCount(int value)用于设置动画循环次数,设置为0表示不循环,设置为ValueAnimation.INFINITE表示无限循环。
cancel()用于取消动画
setRepeatMode(int value)用于设置循环模式,取值为ValueAnimation.RESTART时,表示正序重新开始,当取值为ValueAnimation.REVERSE表示倒序重新开始。
动画时候的监听器
/**
* 监听器一:监听动画变化时的实时值
*/
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
//添加方法为:public void addUpdateListener(AnimatorUpdateListener listener)
/**
* 监听器二:监听动画变化时四个状态
*/
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
关于监听器一:AnimatorUpdateListener就是监听动画的实时变化状态,在onAnimationUpdate(ValueAnimator animation)中的animation表示当前状态动画的实例。这里就不再细讲这个监听器了,这里我们主要讲讲监听器AnimatorListener;
在AnimatorListener中,主要是监听Animation的四个状态,start、end、cancel、repeat;当动画开始时,会调用onAnimationStart(Animator animation)方法,当动画结束时调用onAnimationEnd(Animator animation),当动画取消时,调用onAnimationCancel(Animator animation)函数,当动画重复时,会调用onAnimationRepeat(Animator animation)函数。
添加AnimatorListener的方法是addListener(AnimatorListener listener) ;
下面我们就举个例子来看一下AnimatorListener的使用方法。
我们在上面doRepeatAnim()函数的基础上,添加上AnimatorListener,代码如下:
代码如下
(2)、取消监听
void removeUpdateListener(AnimatorUpdateListener listener);
void removeAllUpdateListeners();
/**
- 移除AnimatorListener
*/
void removeListener(AnimatorListener listener);
void removeAllListeners();
监听是监听 动画是动画。 如果你在移除监听没有取消动画 那么 动画还是会一直运行下去。
常用方法 还有几种。
/**
* 延时多久时间开始,单位是毫秒
*/
public void setStartDelay(long startDelay)
/**
* 完全克隆一个ValueAnimator实例,包括它所有的设置以及所有对监听器代码的处理
*/
public ValueAnimator clone()
repeatAnimator = doRepeatAnim();
//克隆一个新的ValueAnimator,然后开始动画
ValueAnimator newAnimator = repeatAnimator.clone();
newAnimator.setStartDelay(1000);
newAnimator.start();
newAnimator 可以让东西开始。 但是不能停止。
属性动画中的 插入器
二、Evaluator
个人理解。 ofint是你要动画的范围去交。 加速器是你的运动状态。加速减速。等。 然后他返回的是各种进度。 Evaluator返回的进度换算的数值。然后 又一个监听 还记得吗? addup的那个。返回值给他
首先,加速器返回的小数值,表示的是当前动画的数值进度。无论是利用ofFloat()还是利用ofInt()定义的动画都是适用的。因为无论是什么动画,它的进度必然都是在0到1之间的。0表示没开始,1表示数值运动的结束,对于任何动画都是适用的。
但Evaluator则不一样,我们知道Evaluator是根据加速器返回的小数进度转换成当前数值进度所对应的值。这问题就来了,如果我们使用ofInt()来定义动画,动画中的值应该都是Int类型,如果我用ofFloat()来定义动画,那么动画中的值也都是Float类型。所以如果我用ofInt()来定义动画,所对应的Evaluator在返回值时,必然要返回Int类型的值。同样,我们如果用ofFloat来定义动画,那么Evaluator在返回值时也必然返回的是Float类型的值。
所以每种定义方式所对应的Evaluator必然是它专用的;Evaluator专用的原因在于动画数值类型不一样,在通过Evaluator返回时会报强转错误;所以只有在动画数值类型一样时,所对应的Evaluator才能通用。所以ofInt()对应的Evaluator类名叫IntEvaluator,而ofFloat()对应的Evaluator类名叫FloatEvaluator;
在设置Evaluator时,是通过animator.setEvaluator()来设置的,比如:
ObjectAnimator
之前看到的视图动画。(补间动画) 属性动画中的ValueAnimator 都是不方便监控动画的各种状态。 都是我们提前设定好路径。然后按照我们规定好的去各种状态。
ObjectAnimator时可以直接使用。
在开始逐个看这些函数的使用方法前,我们先做一个总结:
1、要使用ObjectAnimator来构造对画,要操作的控件中,必须存在对应的属性的set方法
2、setter 方法的命名必须以骆驼拼写法命名,即set后每个单词首字母大写,其余字母小写,即类似于setPropertyName所对应的属性为propertyName
ObjectAnimator动画原理
PropertyValuesHolder
也就是说ValueAnimator和ObjectAnimator除了通过ofInt(),ofFloat(),ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例,这篇文章我就带大家来看看如何通过ofPropertyValuesHolder()来创建实例的。
由于ValueAnimator和ObjectAnimator都具有ofPropertyValuesHolder()函数,使用方法也差不多,相比而言,ValueAnimator的使用机会不多,这里我们就只讲ObjectAnimator中ofPropertyValuesHolder()的用法。相信大家懂了这篇以后,再去看ValueAnimator的ofPropertyValuesHolder()
下面几段程序上面的注释 是我个人的小心得。欢迎指正 另外 大部分都是学习自启航的文章。特此感谢。
http://blog.csdn.net/harvic880925/article/details/50995268
/** 下面的主要是区别 属性动画中的不同点
*
* 上面的是valueAnimtor 这个 看上面的例子 主要是最数据的这一些操作。只能对数值进行操作。,想要操纵那个控件就要学做监听了。
* 也就是上面的监听器获得数值。然后在监听器中操作这个控件。这个十分不方便。 还要时刻监听,
* 没有办法做到控件和动画紧密的联系起来,所以这就有了
* MyEvaluator 这种求值 于是就有了ObjectAnimotor,他的第一个参数一般都是控件
*
* 重点: ObjectAnimatou比valued多了一个set方法 来反射属性值
*
*
*
* 这些动画操作 步骤都是一样的 第一步显示确定范围。
*
*/
private ValueAnimator doAnimtor(){
ObjectAnimator animator = ObjectAnimator.ofFloat(ID1,"rotationY",0,180,0,180);
animator.setDuration(2000);
animator.setInterpolator(new BounceInterpolator());
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.start();
return animator;
}
/**
* ofPropertyValuesHolder
* 属性动画 用这个也是可以创建的 并且主要是ObjectAnimotor用的比较多,他和ofFloat系列差不多 就是少了第一个参数
*
* 然后要开始想一下了。 这个和objectAnimoto的区别 为什么非要用这个。?
* 这个和那个的不同点? 有什么优点? z之前的我们知道 视图动画和属性动画的优缺点 。没有办法设置点击效果。视图动画只是视觉上的移动。 实际上控件的
* 属性没有任何变化。 所以不能设置任何带有属性的事件。 比如点击事件
*
* valueanitor和ojectanitor的优缺点。便捷程度。 value 必须要时刻要设置监听器 来判断控件的各种动画效果。
* 并且Objectanitor这个也有不同的实现方法,上面的一种有这自己的缺点。当多种动画混合的时候不方便控制其什么时候开始 什么时候结束,没有办法同时控制多种动画
*
* 因此出现了KeyFrame
*
*
* PropertyValuesHolder 这个其实就是细分出来不的。 为了 加入更多的PropertyValuesHolder 效果。 和更多的KeyFrame
*
*
*/
private ValueAnimator dofPropertyValuesHolder(){
PropertyValuesHolder colorHolder1 = PropertyValuesHolder.ofFloat("Rotation",60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ID1,colorHolder1,colorHolder);
animator.setInterpolator(new AccelerateInterpolator());
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.start();
PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("CharText",new CharEvaluator(),new Character('A'),new Character('Z'));
ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(id2, charHolder);
animator1.setDuration(3000);
animator1.setInterpolator(new AccelerateInterpolator());
animator1.start();
return animator;
}
/**
* w我们现在就要想想一个问题。我们这些动画速率的改变 到底是通过什么改变的。
* 插值器和Evaluator 确实可以改变速率 但是他们是做这个的? 插值器是是获取动过的进度、
* Evaluator 是获得动画进度的数值。 比如 我们想做一个效果。中奖名单一直换 我们点击按钮停。有办法吗?答案是
*
*
* 你们可以想一下。 按照之前写的 在我们MyEvaluator中。这个参数系统默认的是int float。我们自定义的话 就可以是各种类型
* ofObject("CharText",new MyEvaluator(),"祁旭","小爽"); 所有的这种方法 你都要保证一个参数的统一。 也就是后两个参数和Evaluator后两个参数类型是一样的
* 至于获取到什么数值。 就看你们自己的方法了。
*/
private ValueAnimator dofPropertyValuesHolder1(){
PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("CharText",new MyEvaluator(),"祁旭","小爽");
ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(id2, charHolder);
animator1.setDuration(3000);
animator1.setInterpolator(new AccelerateInterpolator());
animator1.setRepeatCount(ValueAnimator.INFINITE);
animator1.setRepeatMode(ValueAnimator.REVERSE);
animator1.start();
return animator1;
}
/**
* 因此出现了KeyFrame z这个就是为了解决 速率问题
* Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe frame2 = Keyframe.ofFloat(1, 0);
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);
Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);
animator.setDuration(1000);
animator.start(); 方法和ofObject一样。参数不一样
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
frame1.setInterpolator(new BounceInterpolator());
Keyframe frame2 = Keyframe.ofFloat(1f, 20f);
frame2.setInterpolator(new LinearInterpolator());
就是这样Keyframe 规定了什么时间段 到什么位置 怎么变则没有要求 我们就可以要求BounceInterpolator 插值器一类的实现了。
*
* */
private ValueAnimator dofPropertyValuesHolder2(){
Keyframe frame0 = Keyframe.ofObject(0f, new Character('A'));
Keyframe frame1 = Keyframe.ofObject(0.1f, new Character('L'));
Keyframe frame2 = Keyframe.ofObject(1,new Character('Z'));
/**在每个Keyframe都可以插入插值器 当然最后还不能缺少CharEvaluator
*
*/
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("CharText",frame0,frame1,frame2);
frameHolder.setEvaluator(new CharEvaluator());
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(id2,frameHolder);
animator.setDuration(3000);
animator.start();
return animator;
}
/** 这是针对一个控件他的动画就可以 什么时候加速什么时候减速。 什么时候按照我们做好的插值器去运作。 但是 比如有两个控件呢?
* 我们网上看到的各种和很炫的效果。 都是搭配出来的。这样就需要各种控件去搭配使用。PropertyValuesHolder 这种情况下就不太好用楽
* 因为 出现了AnimatorSet 他可以和上面的一起用。(这么表达不对。 应该说 这个就是多种控件下。这么使用。就可以。)t他可以控制控件执行的先后顺序
*
* 他的几个方法只是负责动画在什么时候开始执行,不干涉动画的执行过程。
*
* playTogether和playSequentially,分别能实现一起开始动画和逐个开始动画。但并不是非常自由的组合动画,
* 比如我们有三个动画A,B,C我们想先播放C然后同时播放A和B。利用playTogether和playSequentially是没办法实现的(真是针对三个以上动画效果的)
*
*/
private void doPlaySequentiallyAnimator(){
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(ID1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(id2, "translationY", 0, 300, 0);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(id2, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(tv1BgAnimator,tv1TranslateY,tv2TranslateY);
animatorSet.setDuration(1000);
animatorSet.start();
}
/**
* AnimatorSet 是一个怎么样的概念呢? 首先看到这个 build 大家 就应该有一个概念性的东西
* 其次。我们回顾一下上面的动画? 发现了什么 每个动画都是独立的。 所以每个都是ObjectAnimator。start来结束。
* 这个不是。是一个结合体、 所以有了一个载体的概念。 把所有的动画放在AnimatorSet.Builder 构建的载体中去。、
* play(playAnim)与before(beforeAnim)共用,则表示在播放beforeAnim之前,先播放playAnim动画;同样,
* 当play(playAnim)与after(afterAnim)共用时,则表示在在播放afterAnim动画之后,再播放playAnim动画。
*/
private void doPlaySequentiallyAnimatorset(){
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(ID1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(ID1, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
AnimatorSet.Builder builder = animatorSet.play(tv1BgAnimator);
builder.with(tv1TranslateY);
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
//
animatorSet.start();
}
/** 这个动画只是监听AnimatorSet的状态和动画无关。
//animatorSet 也会有一些些方法。并且以他为基准。当他没有的时候才会以ObjectAnimator为基准
比如setDuration
* setTarget(mTv2); 设置了这个方法。相当于所有的方法 都是以这个方法都为这个服务。其他的没有作用
* 有一个特例的方法setStartDelay 先执行animatorSet 在执行 ObjectAnimatory方法
*
* - AnimatorSet的延时是仅针对性的延长AnimatorSet激活时间的,对单个动画的延时设置没有影响。
- AnimatorSet真正激活延时 = AnimatorSet.startDelay+第一个动画.startDelay
- 在AnimatorSet激活之后,第一个动画绝对是会开始运行的,后面的动画则根据自己是否延时自行处理。
*
*
*/