这是我在学习过程中总结的知识
目的是希望日后回来看或者需要用的时候可以 一目了然 # 的回顾、巩固、查缺补漏
不追求详细相当于书本的精简版或者说是导读(想看详细的直接对应翻书),但会尽力保证读者都能快速理解和快速使用(随理解加深会总结的更加精简),但必要时会附上一些较详细解释的链接
脚注是空白的:表示还没弄懂的知识,了解后会添加
- View动画:通过对场景里的对象不断做图形变换(平移、缩放、选择、透明度)从而产生动画效果,渐进式动画,支持自定义
- 帧动画:顺序播放一系列图像,即图片切换动画
- 属性动画:动态改变对象的属性从而达到动画效果
7.1 View动画
7.1.1 动画的种类
名称——标签——子类——作用
- 平移动画——translate——TranslateAnimation——移动View
- 缩放——scale——ScaleAnimation——放大或缩小View
- 旋转——rotate——RotateAnimation——旋转View
- 透明度——alpha——AlphaAnimation——改变View 透明度
View 动画即可用代码又可用XML实现,但推荐使用XML(可读性好)
创建动画的文件路径为res/anim/xxx.xml
View动画的使用同样是需要用到的时候再根据效果查资料,不过关于插值器(interpolator)比较难理解要解释一下
android:interpolator
影响动画的速度,非匀速动画就需要它来控制播放过程,还有decelerate_interpolator这个加速减速插值器
android:shareInterpolator
集合中的动画是否共享同一个插值器
android:fillAfter
动画结束后是否停留在结束位置
在Java代码中使用定义好的动画
ListView listView = (ListView) layout.findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
listView.setLayoutAnimation(controller);
7.1.2 自定义View 动画
- 派生一种新动画只需要继承Animation这个抽象类,重写它的initialize(初始化工作)和applyTransformation(进行矩阵变换)
- 矩阵变换是数学上的概念
- 开发中很少用到自定义View 动画
真正要用到再说吧,作者这里也只给出了一个没解释的例子
7.1.3 帧动画
类似于幻灯片播放,系统提供了一个类AnimationDrawable来使用帧动画,需要先在XML定义(animation-list)
然后Java代码中启动动画即可
7.2 View 动画的特殊使用场景
- 在ViewGroup中控制子元素的出场效果
- 在Activity中实现不同的Activity之间的切换效果
7.2.1 LayoutAnimation
作用于ViewGroup,是它子元素出场时都具有这种动画效果.例如ListView、RecycleView
1. 定义LayoutAnimation
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
//按入场周期*0.5来延迟入场动画效果
android:delay="0.5"
//有normal、reverse、random三种
android:animationOrder="reverse"
//指定具体的入场动画
android:animation="@anim/anim_item"/>
2. 指定具体的入场动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fromXDelta="500"
android:toXDelta="0" />
</set>
3. 在XML中应用于ViewGroup
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
//关键在这里
android:layoutAnimation="@anim/anim_layout"
android:background="#fff4f7f9"
android:cacheColorHint="#00000000"
android:divider="#dddbdb"
android:dividerHeight="1.0px"
android:listSelector="@android:color/transparent" />
以上就是全部步骤,同样可以用java代码实现,感兴趣的自查
7.2.2 Activity的切换效果
主要用到overridePendingTransition(int enterAnim,int exitAnim) 这个方法,这个方法必须在startActivity(Intent)或者finish()之后调用才能生效
- enterAnim——Activity被打开时,所需动画资源的id
- exitAnim——Activity被暂停时,所需动画资源的id
当Activity退出时
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
}
当启动一个Activity时
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
Fragment也可以添加切换动画,需要使用support-v4这个兼容包
通过FragmentTransaction中的setCustomAnimations方法来切换,必须是View 动画才行
7.3 属性动画
7.3.1 使用属性动画
- 属性动画可以对任意对象的属性进行动画,不仅是View
- 动画默认时间间隔300ms,帧率10ms/帧
- 意思就是在一个时间间隔内按一定帧率将对象从一个属性值到另一个属性值改变
- 几乎无所不能
- 要采用nineoldandroids来兼容以前版本
比较常用的几个动画类(Java实现方法)是:ValueAnimatior、ObjectAnimatior和AnimatiorSet
也可以XML中实现,文件要定义在res/animator
标签和上面三个对应的是:animator、objectAnimator、set
在实际开发中建议采用代码来实现
7.3.2 理解插值器和估值器
根据他们的功能我们可以大致了解他们的作用
插值器
- TimeInterpolator(时间插值器):根据时间流逝百分比计算属性值改变的百分比
- LinearInterpolator(线性插值器):匀速动画
- AccelerateDecelerateInterpolator:两头慢中间快
- DecelerateInterpolator:动画越来越慢
估值器
- IntEvaluator:针对整型
- TypeEvaluator:根据当前属性改变的百分比计算改变后的属性值
- FloatEvaluator:针对浮点型
- ArgbEvaluator:针对color
还不懂的可以看书P281有具体解释
自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值器需要实现TypeEvaluator
7.3.3 属性动画的监听器
- AnimatorListener:监听动画的开始、结束、取消、重复播放(AnimatorListenerAdapter是它的适配器)
- AnimatorUpdateListener:监听整个动画过程到每一帧,每播放一帧都会被调用一次
7.3.4 对任意属性做动画
View动画根本不支持对宽度进行动画,这时候需要用到属性动画
使用前先了解属性动画原理:按照时间推移多次调用属性的set方法来接近最终达到预设值,所以必须满足两个条件
- 对象必须提供set属性方法,如果动画没有获得该属性的初始值,那么还要提供get属性的方法来获得(否则崩)
- object的set属性方法成功后必须要通过某种方法展现出来,不然看不出效果.类似adapter.notify
为什么不直接getWidth和setWidth呢?
有些控件(继承于TextView)的setWidth的作用其实是设置TextView的最大宽度和最小宽度的
那要满足属性动画的两个原理有3种方法
1.如果有权限,给对象加上get、set方法(基本没权限,因为SDK内部已经实现了,但我们用不上的那种)
2.用一个类来包装原始对象,间接提供get、set(最好用)
代码在书P285中,大致思路是创建一个类,然后通过生成对象的时候把View传给这个类的构造方法,然后再获得View的参数
3.采用ValueAnimator,监听动画过程,自己实现属性的改变
private void performAnimate(final View target, final int start, final int end) {
//5000ms内将一个数从1变到100
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
// 持有一个IntEvaluator对象,方便下面估值的时候使用
private IntEvaluator mEvaluator = new IntEvaluator();
//每一帧都会调用这个方法
@Override
public void onAnimationUpdate(ValueAnimator animator) {
// 获得当前动画的进度值,整型,1-100之间
int currentValue = (Integer) animator.getAnimatedValue();
Log.d(TAG, "current value: " + currentValue);
// 获得当前进度占整个动画过程的比例,浮点型,0-1之间
float fraction = animator.getAnimatedFraction();
// 直接调用整型估值器通过比例计算出宽度,然后再设给Button
target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
target.requestLayout();
}
});
//5000ms内将一个数从1变到100
valueAnimator.setDuration(5000).start();
}
7.4 使用动画的注意事项
1. OOM问题
主要出现在帧动画中,图片数量较多时
2. 内存泄漏
无限循环的动画,需要在Activity退出时及时停止.但是View动画并不存在这个问题
3.兼容性问题
3.0以下的系统要做好适配工作
4. View 动画问题
View动画只是对View的影像做动画,并不是真正改变View的状态,所以可能出现动画完成后View无法隐藏的状态,这时要调用view.clearAnimation()清除动画即可
5. 不要使用px
尽量使用dp,使用px在不同设备有不同效果
6. 动画元素交互
属性动画的单击事件触发位置为移动后的位置,但是View动画仍在原位置1
7. 硬件加速
建议开启,提高动画流畅性