Animation
Android 框架提供了两种动画系统:属性动画和补间动画,这两者都是可选择使用的,但是像比较而言,属性动画是更好的选择,因为其更灵活而且提供更多的属性,除了这两个之外,你还可以利用帧动画,他允许你加载Drawable资源然后以一帧一帧的形式展示他们。
1.Property Animation
引进在Android 3.0(11),它可以让对象的任何属性做动画,包括那些不被渲染到屏幕上的。该系统是可扩展的,并且可以让您的自定义类型的动画属性。
2.View Animation
补间动画是以前的系统提供的,仅仅可以作用在View上面,它是比较容易使用,并提供足够的功能,以满足许多应用程序的需求。
3.Drawable Animation
帧动画可以展示drawable资源一个接一个,像一卷胶卷。如果你想让事情更容易与drawable资源代表这个方法的动画是很有用的,比如一个进程图。
效果:类似gif动图
实现方式:
res/drawable/animation_list_filling.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true"> 执行一次
<item
android:duration="500"
android:drawable="@drawable/ic_heart_0"/>
<item
android:duration="500"
android:drawable="@drawable/ic_heart_25"/>
<item
android:duration="500"
android:drawable="@drawable/ic_heart_50"/>
<item
android:duration="500"
android:drawable="@drawable/ic_heart_75"/>
<item
android:duration="500"
android:drawable="@drawable/ic_heart_100"/>
</animation-list>
代码运用,获得背景,开启动画
ImageView mImageViewEmptying =
(ImageView) findViewById(R.id.animation_list_filling);
((AnimationDrawable)mImageViewEmptying.getBackground())
.start();
例子二
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
AnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}
问题 如何停止动画,让它动画正好播放在指定帧
anim.selectDrawable(0); //选择当前动画的第一帧,然后停止
anim.stop();
二 接下来我的第二不常用 View Animation
它可以实现补间动画(tween animation) ,首先回答一下困扰我很久的问题,补间是个什么鬼?
补间动画,又叫做中间帧动画,只需给出起始和终点动画,中间动画由软件自动生成.
实现方式 xml files and hard-croding 推荐使用xml files 可重用,易读
主要实现类 AnimationSet 和 Animation的子类
在res/anim 下建立xml文件.
顺序也可以一起执行
Interpolator
三:属性动画:Property Animation
属性动画:
proprety animitor
(1)与 view animaitor 区别
支持除了view控件以外的动画
view animator只是重绘了,但并未改变其真实位置
结构
Animator
ValueAnimator 并不能给某个对象或属性添加动画,如果想实调用ValueAnimator.AnimatorUpdateListener
ObjectAnimator 大多数使用这个动画,但是它的限制多一些,比如要求特定的acessor方法对目标对象存在。
包含动画执行周期,是加速还是减速(一种插值运算,可以设置)
Evaluators 计算属性动画的变化值
IntEvaluator 默认给定的计算方式
FloatEvaluator
ArgbEvaluator 对颜色值的变化
TypeEvaluator 一个接口,支持自定义
Interpolator 插值器,加速或减速
属性 | 含义 |
---|---|
@android:anim/accelerate_decelerate_interpolator | 先加速后减速 |
@android:anim/accelerate_interpolator | 加速 |
@android:anim/decelerate_interpolator | 减速 |
@android:anim/anticipate_interpolator | 先向动画的反方向移动一点,在沿动画的方向移动 |
@android:anim/anticipate_overshoot_interpolator | 先向动画的反方向移动一点,在沿动画的方向移动,超过指定终点一点在回弹到终点 |
@android:anim/overshoot_interpolator | 动画到最后的位置会向反方向移动一点。 |
@android:anim/bounce_interpolator | 在终点回弹几次在停在终点 |
@android:anim/cycle_interpolator | 动画周期移动 |
@android:anim/linear_interpolator | 动画匀速移动 |
1.alpha( 渐变)
名称 | 含义 | 备注 |
---|---|---|
android:fromAlpha | 动画开始时的透明度 | float[0,1] 0表示完全透明,1表示完全不透明 |
android:toAlpha | 动画结束时的透明度 | float[0,1] 0表示完全透明,1表示完全不透明 |
2.scale( 缩放)
名称 | 含义 | 备注 |
---|---|---|
android:fromXScale | 动画开始时,X坐标上伸缩的尺寸 | float[0,1] 0.0表示收缩到没有 1.0表示正常无收缩 小于1收缩 大于1放大 |
android:toXScale | 动画结束时,X坐标上伸缩的尺寸 | float[0,1] 0.0表示收缩到没有 1.0表示正常无收缩 小于1收缩 大于1放大 |
android:fromYScale | android:toYScale | android:privotY |
android:privotX | 动画相对于物件的X的开始位置 | [0%,100%] |
50%表示中间
名称 | 含义 | 备注 |
---|---|---|
android:fromXDelta | 动画开始时X坐标上的位置 | integer 默认以自己为参照物 |
android:toXDelta | android:fromYDelta | android:toYDelta |
3.translate(平移)
名称 | 含义 | 备注 |
---|---|---|
android:fromXDelta | 动画开始时X坐标上的位置 | integer 默认以自己为参照物 |
android:toXDelta | android:fromYDelta | android:toYDelta |
名称 | 含义 | 备注 |
---|---|---|
android:fromDegrees(角度,度数) | 动画开始时控件的角度 | 负数:逆时针旋转 正数:顺时针旋转 |
android:fromDegrees | 动画结束时控件的角度 | --- |
android:pivotX | 动画相对于物件的X的开始位置 | [0%,100%],50%表示中间 |
android:pivotY | --- | --- |
4.rotate(旋转)
名称 | 含义 | 备注 |
---|---|---|
android:fromDegrees(角度,度数) | 动画开始时控件的角度 | 负数:逆时针旋转 正数:顺时针旋转 |
android:fromDegrees | 动画结束时控件的角度 | --- |
android:pivotX | 动画相对于物件的X的开始位置 | [0%,100%],50%表示中间 |
android:pivotY | --- | --- |
ValueAnimator应用
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,1f);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//得到的值就是在上面ValueAnimator.ofFloat(0f,1f);中指定的,会在给定的时间内变化
//有时需要调invalidate()方法
float value = (float)animation.getAnimatedValue();
imageView.setScaleX(value);
//
Log.d("MainActivity","属性值"+value);
// imageView.setColorFilter((int)value);
// imageView.invalidate();
}
});
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
//在动画开始的时候执行
}
@Override
public void onAnimationEnd(Animator animation) {
//在动画结束的时候执行
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
valueAnimator.setDuration(1000);
valueAnimator.start();
});
}
注: 如果不想实现所有方法,可以使用AnimatorListenerAdapter,它是一个抽象类,实现了AnimatorListener,和AnimatorPauseListener
标识 | 含义 |
---|---|
APPEARING (appearing) | 一个标识 指示动画作用的控件显示在容器中 |
CHANGE_APPEARING (change_appearing) | 一个标识 指示动画作用的控件正在变化由于一个新的item出现在容器中 |
DISAPPEARING (disappearing) | 一个标识 指示动画作用的控件消失在容器中 |
CHANGE_DISAPPEARING (change_disappearing) | 一个标识 指示动画作用的控件正在变化由于一个新的item出消失容器中 |
为ViewGroup 添加动画 (为里面的itemView在显示或消失的时候添加动画,或显示的view的一些动画处理)
LayoutTrasition setAnimator()
标识 | 含义 |
---|---|
APPEARING (appearing) | 一个标识 指示动画作用的控件显示在容器中 |
CHANGE_APPEARING (change_appearing) | 一个标识 指示动画作用的控件正在变化由于一个新的item出现在容器中 |
DISAPPEARING (disappearing) | 一个标识 指示动画作用的控件消失在容器中 |
CHANGE_DISAPPEARING (change_disappearing) | 一个标识 指示动画作用的控件正在变化由于一个新的item出消失容器中 |
为ViewGroup添加动画的过程(为里面的itemView在显示或消失的时候添加动画,或显示的view的一些动画处理)
tansition = new LayoutTransition();
tansition.setDuration(8000);
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,0f)
.setDuration( tansition.getDuration(LayoutTransition.APPEARING));
tansition.setAnimator(LayoutTransition.APPEARING, animIn);
animIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationY(0f);
}
});
ll.setLayoutTransition(tansition);
源码分析:
setLayoutTransition()
mTansition!=null :清掉动画,清掉监听器
mTabsition==null :赋值,mTabsition == tansition 设置监听 TransitionListener
监听器:
if (transitionType == LayoutTransition.DISAPPEARING) {
startViewTransition(view); //把消失的view保存起来ArraayList
}
Called when a view's visibility has changed. Notify the parent to take any appropriate
* action.onChildVisibilityChanged() //子布局显示改变
if 显示:
mTranstion.showChild(this,child,oldVisibility){
addChild(parent,child,oldVisibility==View.GONE)
}
else :
mTranstion.hideChild(this,child,newVisibibility)
onChildVisibilityChanged
addViewInner
setLayoutTransition
removeDetachedView
layout
specifying 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后,通过PropertyValuesHolder类的方法ofKeyframe一个PropertyValuesHolder对象,然后通过ObjectAnimator.ofPropertyValuesHolder获得一个Animator对象。
用下面的代码可以实现同样的效果(上述代码时间值是线性,变化均匀):
ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);
oa.setDuration(2000);
oa.start();
在横屏中,ImageView位于屏幕右边,向左平移
首先无论在横屏还是竖屏中,都是水平x轴,垂直y轴
动画移动的原点是控件的左上角
当控件指定未屏幕右侧的时候,原点也为控件所在位置的左上角
网友评论