view动画的种类
自定义view动画
view动画的特殊类型
(1)分类
注意:view动画不改变View的属性,点击事件等任在原位置响应。
(2)view动画的实现(推荐使用xml文件实现)
实现方法1:xml文件实现,activity引用
xml文件(路径为res/anim)
//动画完成后是否停留在结束位置
java中引用
Animation animation = AnimationUtils.loadAnimation(this, R.anim.XXX);
mView.startAnimation(animation);
实现方法二:java代码创建
设置对应动画的参数,构造对象,再调用即可
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
alphaAnimation.setDuration(2000);
mImageView.startAnimation(alphaAnimation);
四种动画不能满足需要,自定义动画。
步骤:继承Animation->重写initialize()和applyTransformation()方法:initialize()用于初始化;applyTransformation()用于进行矩阵变换
(1)LayoutAnimation
实现方法一:通过xml文件实现,布局.xml文件中引用
res/anim/anim_layout.xml
//子元素动画的播放顺序:
//normal (正常顺序)、random(随机顺序)、reverse(倒序)。
res/anim/anim_item.xml
布局文件中引用(假设为ListView)
实现方法2:java代码创建
Animation animation = AnimationUtils.loadLayoutAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);//对应android:animation属性
controller.setDelay(0.5);//对应android:delay属性
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);//对应android:animationOrder属性
listView.setLayoutAnimation(controller);//对应android:layoutAnimation属性
(2)Activity的切换效果
startActivity(intent);
//(进入动画.xml,退出动画.xml)
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
帧动画也是View动画的一种,它会按照顺序播放一组预先定义好的图片。对应类AnimationDrawable。
注意:逐帧动画不能使用尺寸过大的图片,否则会造成OOM
方法一:xml定义(位于res/drawable/下),java代码中作为view的背景引入
xml文件
//是否执行一次
//持续时间
activity
mView.setBackgroundResource(R.drawable.XXX);
AnimationDrawable animationDrawable = (AnimationDrawable)mView.getBackground();
animationDrawable.start();
方法二:java代码动态创建
//和上述xml定义方法的效果相同
AnimationDrawable ad = new AnimationDrawable();//1.创建AnimationDrawable对象
for (int i = 0; i < 4; i++) {//2.添加Drawable对象及其持续时间
Drawable drawable = getResources().getDrawable(getResources().getIdentifier("xxx" + i, "drawable", getPackageName()));
ad.addFrame(drawable, 500);
}
ad.setOneShot(false);//3.设置是否执行一次
mView.setBackgroundResource(ad);//4.将帧动画作为view背景
ad.start();//5.播放动画
根节点
点
两个子节点区别:
(1)插值器
(2)估值器(TypeEvaluator)
(1)xml中实现(位于res/animator/),java中引用
res/animator/propertyName.xml(ValueAnimator)
// ObjectAnimator 采用 标签
java代码中引用
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.propertyName);
// 载入XML动画
animator.setTarget(view);
// 设置动画对象
animator.start();
// 启动动画
(2)java代码动态生成
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);
// ofFloat()作用有两个
// 1. 创建动画实例
// 2. 参数设置:参数说明如下
// Object object:需要操作的对象
// String property:需要操作的对象的属性
// float ....values:动画初始值 & 结束值(不固定长度)
// 若是两个参数a,b,则动画效果则是从属性的a值到b值
// 若是三个参数a,b,c,则则动画效果则是从属性的a值到b值再到c值
// 以此类推
// 至于如何从初始值 过渡到 结束值,同样是由估值器决定,此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解
anim.setDuration(500);
// 设置动画运行的时长
anim.setStartDelay(500);
// 设置动画延迟播放时间
anim.setRepeatCount(0);
// 设置动画重复播放次数 = 重放次数+1
// 动画播放次数 = infinite时,动画无限重复
anim.setRepeatMode(ValueAnimator.RESTART);
// 设置重复播放动画模式
// ValueAnimator.RESTART(默认):正序重放
// ValueAnimator.REVERSE:倒序回放
animator.start();
// 启动动画
属性动画主要使用两个接口:AnimatorUpdateListener&AnimatorListener来监听动画的播放过程。
public static interface AnimatorListener {
void onAnimationStart(Animator animation); //动画开始
void onAnimationEnd(Animator animation); //动画结束
void onAnimationCancel(Animator animation); //动画取消
void onAnimationRepeat(Animator animation); //动画重复播放
}
public interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator var1);//在属性动画的属性值变化是回调。
}
在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果。(通过反射调用get/set方法)
由于需要调用对象的get/set方法来动态改变对象的属性,所以对objec的abc属性做动画,想要让动画生效必须满足两个条件:
例子:
对Button的的width属性做动画,没有相应效果(可以验证)。
原因:Button的setWidth是继承自TextView的方法,设置的是TextView的最大宽度,不是设置View的宽,不满足第二条。
解决办法:
(2)用一个类包装原始对象,间接为其提供get和set方法
private void performAnimate() {
ViewWrapper viewWrapper = new ViewWrapper(btn);
ObjectAnimator.ofInt(viewWrapper, "width", 500).setDuration(1000).start();
}
private static class ViewWrapper {
private View mTarget;
public ViewWrapper(View mTarget) {
this.mTarget = mTarget;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
(3)采用ValueAnimator
private void performAnimator(final View target, final int start, final int end) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//持有一个IntEvaluator对象,方便下面估值的时候使用
private IntEvaluator mEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获得当前动画的进度值,整形1-100之间
int currentValue = (int) animation.getAnimatedValue();
//获得当前进度占整个动画之间的比例,浮点0-1之间
float fraction = animation.getAnimatedFraction();
//直接使用整形估值器,通过比例计算宽度,然后再设置给按钮
target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}
这个问题主要还是帧动画中,当图片过多的时候就OOM了,这个在实际的开发中尤其注意,尽量避免使用帧动画
在属性动画中有一类无限循环的动画,如果你在activity退出后不停止的话,可能就会存在这个问题了
动画在3.0以下的系统上有缺陷,最好做好适配工作
view动画死对view的影像做动画,并不是真正的改变view的状态,因此有时候会出现完成后view无法隐藏的现象,即setVisibility(View.GONE),这个时候只要调用clearAnimation清除动画即可
在进行动画的过程,要尽量使用dp,使用px会导致适配问题
将view移动后,在3.0以前的系统,不管是view动画还是属性动画,新位置都无法调用单机事件,同时老位置却可以,从3.0之后,属性动画的点击事件触发位置为移动后的位置,但是view动画仍然在原位置。
使用动画的过程,建议开启硬件加速,这样会提高动画的流畅性 动画