Android 动画
- Android动画分为三种:
- 属性动画
- 帧动画
- View动画
- View动画支持4种效果
平移,旋转,缩放,透明度
- View动画对于四大类
- TranslateAnimation=> <translate/>
- ScaleAnimation=> <scale/>
- RotateAnimation=> <rotate/>
- AlphaAnimation=> <alpha/>
还有个集合类
AnimationSet =><set/>
- 动画在res文件夹中的位置:
View 动画=>res/anim/filename.xml
- View动画创建方式:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:zAdjustment="normal">
<translate
android:duration="100"
android:fromXDelta="0"
android:fromYDelta="0"
android:interpolator="@android:anim/linear_interpolator"
android:toXDelta="100"
android:toYDelta="100" />
<rotate
android:duration="100"
android:fromDegrees="0"
android:toDegrees="90" />
</set>
Button button = new Button(this);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_test);
button.startAnimation(animation);
或者代码创建
//代码创建
Animation anim = new AlphaAnimation(0,1);
anim.setDuration(1000);
button.startAnimation(anim);
- 给View动画添加监听
Animation的setAnimationListener()方法添加监听
public static interface AnimationListener {
/**
* <p>Notifies the start of the animation.</p>
*
* @param animation The started animation.
*/
void onAnimationStart(Animation animation);
/**
* <p>Notifies the end of the animation. This callback is not invoked
* for animations with repeat count set to INFINITE.</p>
*
* @param animation The animation which reached its end.
*/
void onAnimationEnd(Animation animation);
/**
* <p>Notifies the repetition of the animation.</p>
*
* @param animation The animation which was repeated.
*/
void onAnimationRepeat(Animation animation);
}
}
- 自定义View动画
继承Animation抽象类,重写initialize和applyTransformation方法
initialize 做些初始化工作
applyTransformation 做些矩阵变换工作,很多时候需要Camera类来简化矩阵变换。
- 帧动画 AnimationDrawable 作为Drawable设置给View的背景,然后获取AnimationDrawable,通过start开启动画
- View动画的特殊使用,在ViewGroup中使用动画,作为控制子元素的出场效果。
LayoutAnimation
LayoutAnimation用做ViewGroup,为ViewGroup指定一个出场动画,这样它的子元素出场时都会具有这样动画。
- xml中定义LayoutAnimation
//res/anim/layout_animation_test.xml
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/animation_test"
/>
其中animation_test为入场动画
- 为ViewGroup指定android:layoutAnimation属性:android:layoutAnimation:"@anim/layout_animation_test"
<ListView
android:id="@+id/vmarqueeview"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@android:color/holo_blue_light"
android:divider="@null"
android:layout_centerInParent="true"
android:layoutAnimation="@anim/layout_animation_test"
android:scrollbars="none" />
除了通过xml指定LayoutAnimation之外, 还可以通过LayoutAnimationContoller来实现。
ListView listView = (ListView) findViewById(R.id.vmarqueeview);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_test);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);
- Activity的动画切换效果 用到了View动画
overridePendingTransition(int enterAnim, int exitAnim)
调用时机:startActivity之后,finish之后。
- Fragment是api11新引入的类,为了兼容需要使用support-v4包
- Fragment切换动画 使用的是View动画
FragmentTransaction的setCustomAnimations()方法来添加切换动画。
-
属性动画
api 11引入的新特性,和View动画不同,它对作用对象进行了拓展,属性动画可以对任何对象做动画,甚至还可以没有对象,不仅支持View动画的四种简单变化,还支持更多花样。
- 属性动画xml定义的文件夹:res/animator/xxx.xml
- 属性动画实现在一段时间内完成一个对象属性值的变化。
- api 11之前使用NineOldAndroids来兼容之前版本。https://nineoldAndroid.com
- nineoldandroids 使用代理View来实现属性动画,本质还是View动画。
- 常用属性动画
ValueAnimator,ObjectAnimator,AnimatorSet
ObjectAnimator继承ValueAnimator,AnimatorSet是动画集合。
- 改变一个对象的translationY属性,让其沿着Y轴平移。
ObjectAnimator.ofFloat(vMarqueeView, "translationY", -vMarqueeView.getHeight()).start();
- 改变一个对象的背景色属性,3秒内实现颜色渐变,动画会无线循环且有反转效果。
ObjectAnimator.ofFloat(vMarqueeView, "translationY", -vMarqueeView.getHeight()).start();
ValueAnimator colorAnim = ObjectAnimator.ofInt(vMarqueeView, "backgroundColor", /*RED*/0xffff8080, /*BLUE*/0xff8080ff);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
- 属性动画动画集,AnimatorSet
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(vMarqueeView, "rotationX", 0, 360),
ObjectAnimator.ofFloat(vMarqueeView, "translationY", 0, 90),
ObjectAnimator.ofFloat(vMarqueeView, "scaleX", 1, 1.5f),
ObjectAnimator.ofFloat(vMarqueeView, "alpha", 1, 0.25f, 1)
);
set.setDuration(1000);
set.start();
- xml 中定义属性动画
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<!--android:ordering=["together"|"sequentially"]-->
<objectAnimator
android:duration="int"
android:propertyName="string"
android:repeatCount="int"
android:repeatMode="reverse"
android:startOffset="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:valueType="intType"|"floatType"
/>
<animator
android:duration="int"
android:repeatCount="int"
android:repeatMode="reverse"
android:startOffset="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:valueType="intType"|"floatType"
/>
</set>
ordering属性:"together"和"sequentially",前者表示同时播放,后者表示按顺序一个个播放。
具体各属性定义 ->p279
使用上面的动画:
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.animator_test);
set.setTarget(vMarqueeView);
set.start();
- 插值器(TimeInterpolator BaseInterpolator 继承TimeInterpolator) 估值器(TypeEvaluator)
插值器:通过自定义的算法根据时间流逝百分比计算当前属性值改变的百分比
估值器:根据当前属性改变百分比来计算改变后的属性值
例子参考:p281
- 属性动画监听器
AnimatorListener 和 AnimatorUpdateListener
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
AnimatorListenerAdaptor 是AnimatorListener的适配器类,可以有选择的实现AnimatorListener中的方法,而不是必须全部实现。
AnimatorUpdateListener 比较特殊,会监听整个动画过程,动画由许多帧组成,每播放一帧,onAnimatorUpdate就会调用一次,
- ObjectAnimator使用注意:
- 对象的属性必须提供get,set方法,
- set方法必须能完成某种效果,能体现出来。
如果目标对象的set,get方法未提供或者不能达到目的效果,则可以按照官方提供的方法:
- 如果有权限就加上get,set
- 用一个类来包装原始对象,添加get,set
- 采用ValueAnimator,监听动画过程,自己手动改变属性,达到动画效果。
- ValueAnimator本身不作用于任何对象,直接使用它没有任何动画效果,通过它的监听回调的值,来改变属性,来达到动画效果。
- 属性动画源码用到了反射和jni调用 p291
-
使用动画的几点注意事项
-
OOM问题
这个问题主要出现在帧动画中,当图片数量较多,且图片较大时,容易出现OOM,尽量避免帧动画 -
内存泄漏,针对无线循环的动画,属性动画存在持有Activity对象无法释放导致内存泄漏情况,经过验证View动画不存在。
-
View动画的问题,View动画只是对View的影像做动画,并非真正改变View,因此有时会出现动画完成后无法隐藏View的问题,setVisibility失效,这时,需要使用view.clearAnimation() ,清除动画解决。
-
兼容性问题,动画在3.0(11)下有兼容性问题,需做好适配
-
不使用px,为了机型适配,建议使用dp
-
动画元素交互,在3.0之前的系统,动画效果发生后,均无法在新位置触发点击事件,老位置仍可触发,3.0之后,属性动画会在新位置点击有效,View动画还是不行。
-
可以开启硬件加速,来提高动画的流畅度。
网友评论