动画分为三种:帧动画,属性动画,视图动画,其实帧动画也属于视图动画的一种,只不过它和平移、旋转等常见的View动画表现形式上略有不同。帧动画是顺序播放一组预先定义好的图片,类似于电影播放,使用xml定义,使用起来比较简单,可以理解为图片的切换动画,很显然,如果图片过大就会导致OOM。视图动画通过对场景里的对象不断做图像转换(平移,缩放,旋转,透明度)从而产生动画效果,它是一种渐进式动画并且View动画支持自定义。它有一个缺点:当执行了图形转换之后,View的事件响应不是在现有的位置,而是在原位置,并且不支持在动画进行中进行回调。属性动画是google在API 11以后推出的新的动画方式,我们一般使用nineoldandroids兼容库去实现对低版本动画的兼容。属性动画解决了视图动画的不足。由于我们的动画牵涉到宽度、高度的变化,并且变化以后还要能响应事件,所以都是使用属性动画来实现。属性动画使用起来也非常简单,可以参考下面实现的两个方法自己去设置动画参数;
一 视图动画
View动画的作用对象是View,它支持4种动画效果,分别是平移动画、缩放动画、旋转动画、和透明动画。另外帧动画也属于View动画,但是帧动画的表现形式和上面的四种不太一样。
View动画变换效果对应这Animation的4个子类:TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。四种动画既可以通过XML来定义,也可以通过代码来创建,对于View动画来说,建议通过XML来定义,因为可读性更好。
View动画的xml定于语法固定,举个栗子:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <!-- 动画效果 从看不见到可以看见,也就是0到1,变幻时间为5000毫秒--> <scale android:duration="100" android:fromXScale="0.95" android:fromYScale="0.95" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.0" android:toYScale="1.0" /> <alpha android:duration="100" android:fromAlpha="0" android:toAlpha="1" /><translate android:duration="300" android:fillAfter="true" android:fromYDelta="0" android:interpolator="@android:anim/accelerate_interpolator" android:toYDelta="-100%" /><rotate android:fromDegrees="float" android:toDegrees="float" android:pivotX="float" android:pivotY="float" /></set>
Animationan = AnimationUtils.loadAnimation(getContext(), R.anim.auto_left_in);
left_panel.startAnimation(an);
除了在XML中定义,也可以通过代码来创建动画。
AlphaAnimation alphaAnimation=new AlphaAnimation(0,1); alphaAnimation.setDuration(300); view.startAnimation(alphaAnimation);View动画的特殊使用场景
1. LayoutAnimationLayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,这样,当它的子元素出场时就会具有这种动画效果。这种效果是常被用在ListView上,这就可以实现Listview的每个item都已一定的动画形式出现。举个栗子:<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.5" android:nimationOrder="normal" android:animation="@anim/anim_item"/>2. Activity的切换效果Activity有默认的切换效果,但是这个效果我们是可以自定义的,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity(Intent)或者finish()之后调用才能生效。二 帧动画
帧动画是顺序播放一组预先定义好的图片,类似于电影播放,系统提供了AnimaitonDrable来使用帧动画XML:<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="" android:duration="500"/> <item android:drawable="" android:duration="500"/> <item android:drawable="" android:duration="500"/> </animation-list>mButton.setBackgroundResource(R.drawable.test);AnimationDrawable drawable=(AnimationDrawable)mButton.getBackground();drawable.start();三 属性动画
属性动画是API 11之后新加入的特性,和View动画不同,它对作用对象进行了扩展,属性动画可以对任何对象做动画。除了作用对象进行扩展以外,属性动画也得到了加强,不再像View动画那样只能支持四种简单的变换。属性动画中有ValueAnimatior,ObjectAnimator和AnimatorSet等概念。属性动画几乎是无所不能的,只要对象有这个属性,它都能实现动画效果。为了兼容API11以下版本,我们通常用nineoldandroids来兼容低级版本。1. 改变对象的translationY属性,让其沿着Y轴向上移动一段距离。ObjectAnimator.ofFloat(target, "translationY", 500).setDuration(325).start();2. 改变一个对象的背景色属性,典型的情况是改变一个View的背景色。ValueAnimator transAnim = ObjectAnimator.ofFloat(view, "backgroundColor","0Xffff8080","0Xff8080ff");
transAnim.setDuration(325); transAnim.setInterpolator(new LinearOutSlowInInterpolator());transAnim.setEvaluator(new ArgbEvaluator()); transAnim.start();3.动画集合AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(view, "ScaleX", 1, 0.92f), ObjectAnimator.ofFloat(view, "ScaleY", 1, 0.92f), ObjectAnimator.ofFloat(view, "alpha", 1, 0) ); set.setInterpolator(new FastOutLinearInInterpolator()); set.setDuration(175).start();属性动画也可以动过xml来定义:<set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Before rotating, immediately set the alpha to 0. --> <objectAnimator android:valueFrom="1.0" android:valueTo="0.0" android:propertyName="alpha" android:duration="0" /> <!-- Rotate. --> <objectAnimator android:valueFrom="180" android:valueTo="0" android:propertyName="rotationY" android:interpolator="@android:interpolator/accelerate_decelerate" android:duration="@integer/card_flip_time_full" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> <objectAnimator android:valueFrom="0.0" android:valueTo="1.0" android:propertyName="alpha" android:startOffset="@integer/card_flip_time_half" android:duration="1" /> </set>AnimatorSet set=(AnimatorSet) AnimatorInflater.loadAnimator(context,R.anim.test); set.setTarget(view); set.start();4. 插值器(TimeInterpolator)与估值器(TypeEvaluator)
插值器:根据时间的流逝的百分比来计算出当前属性值改变的百分比。系统预定义的有几种插值器 (LinearOutSlowInInterpolator
,FastOutLinearInInterpolator,FastOutSlowInInterpolator,LookupTableInterpolator,PathInterpolatorCompat)满足日常使用要求,若有特殊要求,也可以重写插值器的实现方法,比较简单;
package android.support.v4.view.animation; public class FastOutSlowInInterpolator extends LookupTableInterpolator { /** * Lookup table values sampled with x at regular intervals between 0 and 1 for a total of * 201 points. */ private static final float[] VALUES = new float[] { 0.0000f, 0.0001f, 0.0002f, 0.0005f, 0.0009f, 0.0014f, 0.0020f, 0.0027f, 0.0036f, 0.0046f, 0.0058f, 0.0071f, 0.0085f, 0.0101f, 0.0118f, 0.0137f, 0.0158f, 0.0180f, 0.0205f, 0.0231f, 0.0259f, 0.0289f, 0.0321f, 0.0355f, 0.0391f, 0.0430f, 0.0471f, 0.0514f, 0.0560f, 0.0608f, 0.0660f, 0.0714f, 0.0771f, 0.0830f, 0.0893f, 0.0959f, 0.1029f, 0.1101f, 0.1177f, 0.1257f, 0.1339f, 0.1426f, 0.1516f, 0.1610f, 0.1707f, 0.1808f, 0.1913f, 0.2021f, 0.2133f, 0.2248f, 0.2366f, 0.2487f, 0.2611f, 0.2738f, 0.2867f, 0.2998f, 0.3131f, 0.3265f, 0.3400f, 0.3536f, 0.3673f, 0.3810f, 0.3946f, 0.4082f, 0.4217f, 0.4352f, 0.4485f, 0.4616f, 0.4746f, 0.4874f, 0.5000f, 0.5124f, 0.5246f, 0.5365f, 0.5482f, 0.5597f, 0.5710f, 0.5820f, 0.5928f, 0.6033f, 0.6136f, 0.6237f, 0.6335f, 0.6431f, 0.6525f, 0.6616f, 0.6706f, 0.6793f, 0.6878f, 0.6961f, 0.7043f, 0.7122f, 0.7199f, 0.7275f, 0.7349f, 0.7421f, 0.7491f, 0.7559f, 0.7626f, 0.7692f, 0.7756f, 0.7818f, 0.7879f, 0.7938f, 0.7996f, 0.8053f, 0.8108f, 0.8162f, 0.8215f, 0.8266f, 0.8317f, 0.8366f, 0.8414f, 0.8461f, 0.8507f, 0.8551f, 0.8595f, 0.8638f, 0.8679f, 0.8720f, 0.8760f, 0.8798f, 0.8836f, 0.8873f, 0.8909f, 0.8945f, 0.8979f, 0.9013f, 0.9046f, 0.9078f, 0.9109f, 0.9139f, 0.9169f, 0.9198f, 0.9227f, 0.9254f, 0.9281f, 0.9307f, 0.9333f, 0.9358f, 0.9382f, 0.9406f, 0.9429f, 0.9452f, 0.9474f, 0.9495f, 0.9516f, 0.9536f, 0.9556f, 0.9575f, 0.9594f, 0.9612f, 0.9629f, 0.9646f, 0.9663f, 0.9679f, 0.9695f, 0.9710f, 0.9725f, 0.9739f, 0.9753f, 0.9766f, 0.9779f, 0.9791f, 0.9803f, 0.9815f, 0.9826f, 0.9837f, 0.9848f, 0.9858f, 0.9867f, 0.9877f, 0.9885f, 0.9894f, 0.9902f, 0.9910f, 0.9917f, 0.9924f, 0.9931f, 0.9937f, 0.9944f, 0.9949f, 0.9955f, 0.9960f, 0.9964f, 0.9969f, 0.9973f, 0.9977f, 0.9980f, 0.9984f, 0.9986f, 0.9989f, 0.9991f, 0.9993f, 0.9995f, 0.9997f, 0.9998f, 0.9999f, 0.9999f, 1.0000f, 1.0000f }; public FastOutSlowInInterpolator() { super(VALUES); } }估值器:类型估值算法,根据当前属性改变的百分比来计算改变后的属性值,系统预设置的有IntEvaluator,FloatEvaluator,ArgbEvaluator。估值器和插值器是实现非迅速动画的重要手段。
5. 属性动画监听器
a) 属性动画提供了监听器用于监听动画的播放过程,主要有如下两个接口:AnimatorUpdateListener和AnimatorListerer。
AnimatorListerer定义如下:public static interface AnimatorListener { void onAnimationStart(Animator animation); void onAnimationEnd(Animator animation); void onAnimationCancel(Animator animation); void onAnimationRepeat(Animator animation); }b) AnimatorUpdateListener定于如下:
public static interface AnimatorUpdateListener {void onAnimationUpdate(ValueAnimator animation); }6. 对任意属性做动画
举个栗子:
对一个Button的宽度进行变化,按下面这样写,是否正确?
ObjectAnimator.ofFloat(target, "width", 500).setDuration(325).start();
答案是否定的。因为Button没有setWidth方法来改变其宽度,Button继承自TextView,而TextView的setWidth方法不是用来设置TextView的宽度的,而是设置其最大宽度与最小宽度。具体来说android:layout_width对应textView的width属性,而不是android:width。总之,通过这个方法,无法改变TextView的宽度。官方文档给出了3种解法:
1. 改你的对象加上get和set方法,如果你权限的话。
2. 用一个类来包装原始对象,间接为期提供get与set方法;
3. 采用ValueAnimator,监听动画的过程,自己实现属性动画。
对于2,举个栗子:
ViewWrapperwrapper=new ViewWrapper(target);
ObjectAnimator.ofFloat(wrapper, "width", 500).setDuration(325).start();
private static class ViewWrapper { private View mTarget; public ViewWrapper(View target) { mTarget = target; } public int getWidth() { return mTarget.getLayoutParams().width; } public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }对于3,举个栗子:
ValueAnimator transAnim = ObjectAnimator.ofInt(1, 100); transAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { private IntEvaluator mEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animation) { //获取当前动画进度值,整型,1~100 int currentValue = (Integer) animation.getAnimatedValue(); float fraction = animation.getAnimatedFraction(); target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end); target.requestLayout(); } }); transAnim.setDuration(325); transAnim.setInterpolator(new LinearOutSlowInInterpolator()); transAnim.start();
累死了,今天就写这么多。
Android动画深入分析
最新推荐文章于 2021-06-23 09:53:40 发布