Android动画解析(二)
来源:互联网 发布:农村淘宝地址怎么改 编辑:程序博客网 时间:2024/06/08 16:43
一、插值器和估值器:
Interpolator(插值器)和TypeEvaluator(估值器)是实现非匀速动画的重要手段
1、Interpolator: 过渡值变化的规则( 控制动画的进度 )
* AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速* AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速* AnticipateInterpolator 开始的时候向后然后向前甩* AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值* BounceInterpolator 动画结束的时候弹起* CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线* DecelerateInterpolator 在动画开始的地方快然后慢* LinearInterpolator 以常量速率改变* OvershootInterpolator 向前甩一定值后再回到原来位置2、自定义插值器:
实现TimeInterpolator。TimeInterpolator:时间插值器,根据时间的百分比计算属性改变的百分比
class MyInterploator implements TimeInterpolator{ @Override public float getInterpolation(float input) { return 1-input; } }在getInterpolation函数中,直接把input值返回,即以当前动画的进度做为动画的数值进度,这也就表示当前动画的数值进度与动画的时间进度一致
3、evaluator 估值器
将从加速器返回的数字进度转成对应的数字值。
通过在AnimatorUpdateListener监听器使用animation.getAnimatedValue()函数拿到Evaluator中返回的数字值。
ofInt()对应的Evaluator类名叫IntEvaluator,而ofFloat()对应的Evaluator类名叫FloatEvaluator;
public class IntEvaluator implements TypeEvaluator<Integer> { /** * This function returns the result of linearly interpolating the start and end values, with * <code>fraction</code> representing the proportion between the start and end values. The * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>, * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>, * and <code>t</code> is <code>fraction</code>. * * @param fraction The fraction from the starting to the ending values * @param startValue The start value; should be of type <code>int</code> or * <code>Integer</code> * @param endValue The end value; should be of type <code>int</code> or <code>Integer</code> * @return A linear interpolation between the start and end values, given the * <code>fraction</code> parameter. */ public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); }}
fraction就是加速器中的返回值,表示当前动画的数值进度,百分制的小数表示。
startValue和endValue分别对应ofInt(int start,int end)中的start和end的数值;
4、自定义估值器:public class MyEvaluator implements TypeEvaluator<Integer> { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(200+startInt + fraction * (endValue - startInt)); } }5、ArgbEvalutor 颜色过度的估值器
ValueAnimator animator = ValueAnimator.ofInt(0xffffff00, 0xff0000ff);animator.setEvaluator(new ArgbEvaluator());animator.setDuration(3000); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){ @Override public void onAnimationUpdate (ValueAnimator animation){ int curValue = (int) animation.getAnimatedValue(); tv.setBackgroundColor(curValue); } }); animator.start();
三、ObjectAnimator
继承于ValueAnimator
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
- 第一个参数用于指定这个动画要操作的是哪个控件
- 第二个参数用于指定这个动画要操作这个控件的哪个属性
- 第三个参数是可变长参数,这个就跟ValueAnimator中的可变长参数的意义一样了,就是指这个属性值是从哪变到哪。
1、属性动画的原理:
object必须提供该属性的set方法,多次调用set方法,每次传给set的值不一样。
如果没初始值,还需要get方法,因为系统要获取属性的初始值。
例如:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。
public void setRotation(float rotation) { if (rotation != getRotation()) { // Double-invalidation is necessary to capture view's old and new areas invalidateViewProperty(true, false); mRenderNode.setRotation(rotation); invalidateViewProperty(false, true); invalidateParentIfNeededAndWasQuickRejected(); notifySubtreeAccessibilityStateChangedIfNeeded(); }}调用的内部进行属性调整,通过invalidate进行重绘。
View关于动画的set方法如下:
//透明度:alpha
public void setAlpha(float alpha)
//旋转度数:rotation、rotationX、rotationY
public void setRotation(float rotation)
public void setRotationX(float rotationX)
public void setRotationY(float rotationY)
//平移:translationX、translationY
public void setTranslationX(float translationX)
public void setTranslationY(float translationY)
//缩放:scaleX、scaleY
public void setScaleX(float scaleX)
public void setScaleY(float scaleY)
public class MyPointView extends View { private Point mPoint = new Point(100); public MyPointView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { if (mPoint != null){ Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(300,300,mPoint.getRadius(),paint); } super.onDraw(canvas); } void setPointRadius(int radius){ mPoint.setRadius(radius); invalidate(); } //初始值 public int getPointRadius(){ return 20; }}
private void doPointViewAnimation(){ ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100); animator.setDuration(2000); animator.start();}
四、PropertyValuesHolder
1、保存动画过程所需操作的属性和对应的值。
ofFloat内部实现是将传入的参数封装为PropertyValuesHolder 。
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { ObjectAnimator anim = new ObjectAnimator(target, propertyName); anim.setFloatValues(values); return anim;}
@Overridepublic void setFloatValues(float... values) { if (mValues == null || mValues.length == 0) { // No values yet - this animator is being constructed piecemeal. Init the values with // whatever the current propertyName is if (mProperty != null) { setValues(PropertyValuesHolder.ofFloat(mProperty, values)); } else { setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); } } else { super.setFloatValues(values); }}
public void setValues(PropertyValuesHolder... values) { int numValues = values.length; mValues = values; mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); for (int i = 0; i < numValues; ++i) { PropertyValuesHolder valuesHolder = values[i]; mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); } // New property/values/target should cause re-initialization prior to starting mInitialized = false;}2、构造PropertyValuesHolder:
public static PropertyValuesHolder ofFloat(String propertyName, float... values)public static PropertyValuesHolder ofInt(String propertyName, int... values)public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, Object... values)public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
propertyName: 需要操作的参数名
values : 属性对应可变参数
evaluator:估值器
3、返回ObjectAnimator对象ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
target: 需要执行动画的控件
values : 可以是多个PropertyValuesHolder,每一个PropertyValuesHolder对一个属性做动画,多个实例可对控件多个属性动画。
PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);animator.setDuration(3000);animator.setInterpolator(new AccelerateInterpolator());animator.start();类似于动画集合
(3)ofObject:
例:改变TextView textSize属性
注意:改变属性的类型要匹配,控件有set方法(可自己扩展)
private void startAnimator() { PropertyValuesHolder charHolder = PropertyValuesHolder.ofObject("textSize",new FloatEvaluator(),10f,20f); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(myText, charHolder); animator.setDuration(5000); animator.setInterpolator(new AccelerateInterpolator()); animator.start();}class FloatEvaluator implements TypeEvaluator<Float>{ @Override public Float evaluate(float fraction, Float startValue, Float endValue) { return fraction * (endValue -startValue); }}4、Keyframe: 关键帧,为了控制动画速率
/** * ofFloat */public static Keyframe ofFloat(float fraction)public static Keyframe ofFloat(float fraction, float value)/** * ofInt */public static Keyframe ofInt(float fraction)public static Keyframe ofInt(float fraction, int value)
fraction:当前进度
value:当前位置
例:Keyframe frame0 = Keyframe.ofFloat(0f, 0);Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);Keyframe frame2 = Keyframe.ofFloat(1, 0);PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder); animator.setDuration(1000); animator.start();(2)常用函数:
/** * 设置fraction参数,即Keyframe所对应的进度 */public void setFraction(float fraction)/** * 设置当前Keyframe所对应的值 */public void setValue(Object value)/** * 前一个Keyframe到当前Keyframe期间所对应的插值器 */public void setInterpolator(TimeInterpolator interpolator)
注:
- 如果去掉第0帧,将以第一个关键帧为起始位置
- 如果去掉结束帧,将以最后一个关键帧为结束位置
- 使用Keyframe来构建动画,至少要有两个或两个以上帧
五、AnimatorSet
1、 playSequentially表示所有动画依次播放,playTogether表示所有动画一起开始。
public void playSequentially(Animator... items);public void playSequentially(List<Animator> items);public void playTogether(Animator... items);public void playTogether(Collection<Animator> items);
private void doPlaySequentiallyAnimator(){ ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 300, 0); ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY); animatorSet.setDuration(1000); animatorSet.start();}
注:
- 如果去掉第0帧,将以第一个关键帧为起始位置
- 如果去掉结束帧,将以最后一个关键帧为结束位置
- 使用Keyframe来构建动画,至少要有两个或两个以上帧
2、AnimatorSet.Builder
//表示要播放哪个动画public Builder play(Animator anim)//和前面动画一起执行public Builder with(Animator anim)//执行前面的动画后才执行该动画public Builder before(Animator anim)//执行先执行这个动画再执行前面动画public Builder after(Animator anim)//延迟n毫秒之后执行动画public Builder after(long delay)串行方式执行:
ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator);animatorSet.setDuration(2000);animatorSet.start();3、函数:
//设置单次动画时长public AnimatorSet setDuration(long duration);//设置加速器public void setInterpolator(TimeInterpolator interpolator)//设置ObjectAnimator动画目标控件public void setTarget(Object target)//设置延时开始动画时长(只是延长AnimatorSet的开始时间)public void setStartDelay(long startDelay)
四、对任意属性做动画(自定义动画):
1、属性动画的原理:
(1)object必须提供该属性的set方法,多次调用set方法,每次传给set的值不一样。
如果没初始值,还需要get方法,因为系统要获取属性的初始值。
(2)对于属性的改变必须通过某种ui的变化体现出来(不然动画无效)
解决方式:
1、给你的对象加上set和get方法(或者用一个类包装原始类,间接提供get和set方法。)
public class Animator { private Button button; private void performAnimate(){ //按钮点击后执行的动画 ViewWrapper viewWrapper = new ViewWrapper(button); ObjectAnimator.ofInt(viewWrapper,"width",500).setDuration(5000).start(); } private static class ViewWrapper{ private View mtagerView; public ViewWrapper(View target){ mtagerView = target; } public int getWidth(){ return mtagerView.getLayoutParams().width; } public void setWidth(int width){ mtagerView.getLayoutParams().width = width; mtagerView.requestLayout(); } }}2、采用ValueAnimator,监听动画过程,自己实现属性的改变
public void performAnimate(final int start, final int end, final View targetView){ final ValueAnimator valueAnimator =ValueAnimator.ofInt(1,100); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { //整形估值器,估值时使用 private IntEvaluator intEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animation) { //获取动画的进度 int currValue=(Integer) animation.getAnimatedValue(); //当前进度占整个动画的比例 float fraction= animation.getAnimatedFraction(); //通过比例计算出宽度,然后在设给Button targetView.getLayoutParams().width=intEvaluator.evaluate(fraction,start,end); targetView.requestLayout(); } }); valueAnimator.setDuration(5000).start(); //5000ms内1-100}
3、使用动画注意事项
- OOM:数量较多并图片较大
- 内存泄露:无限循环动画,需要在Activity中退出时停止
- 兼容性问题
- View动画完成,View无法隐藏。需要调用clearAnimation清除View动画
- 尽量使用dp
- 动画过程,开启硬件加速
阅读全文
0 0
- Android动画解析(二)
- Android动画解析(二)-----属性动画
- Android属性动画完全解析(二)
- Android动画全解析(二)
- Android动画详解(二)属性动画完全解析(上)
- Android 动画(二)
- Android动画解析(二)—— Tween Animation(补间动画)
- Android 动画解析(二) 补间动画(Tween Animation)
- android动画解析(初级)
- android动画(Animation)解析
- Android动画解析(一)
- Android动画之属性动画(二)
- Android 动画(二) 属性动画
- Android动画机制-属性动画(二)
- Android动画(二)-属性动画
- Android动画动画二
- OSG动画库Animation解析(二)
- android Tween动画 (二)
- Spring-Boot使用jsp
- java-JDBC访问数据库
- 如何查看Java中的native源码?
- 认识python的表达式
- Java 基础字符串之StringBuilder和StringBuffer区别
- Android动画解析(二)
- 协变,逆变,上界,下界
- 详解linux之NFS文件共享服务
- 二分图复习笔记
- Moving Tables
- 看书的收获
- eclipse常用快捷键
- 图像基础9 插值与缩放
- 什么是机器学习