关于动画的使用
来源:互联网 发布:淘宝自检工具 编辑:程序博客网 时间:2024/05/13 04:39
1、概述
Android提供了几种动画类型:
- View Animation(Tween Animation)
- Drawable Animation(Frame Animation)
Property Animation
View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且有一定的局限性。比如:你希望View有一个颜色的切换动画;你 希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的位置;这些View Animation都无法做到。这就是Property Animation产生的原因。View Animation 移动控件之后,控件的点击事件还在原地,而Property Animation的控件点击事件会移动到动画结束的地方。
2、相关API
Property Animation就是通过动画的方式改变对象的属性,属性:
Duration动画的持续时间,默认300ms。
Time interpolation:时间差值,类似于LinearInterpolator、AccelerateDecelerateInterpolator,定义动画的变化率。
TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。
Frame refresh delay:帧刷新延迟,对于你的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态;基本不用管。
ViewPropertyAnimator:
相关的类
ObjectAnimator 动画的执行类,
ValueAnimator 动画的执行类,
AnimatorSet 用于控制一组动画的执行:线性,一起,每个动画的先后执行等。
AnimatorInflater 用户加载属性动画的xml文件
TypeEvaluator 类型估值,主要用于设置动画操作属性的值。
TimeInterpolator 时间插值
总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性。
TypeEvalutors
根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
● IntEvaluator:属性的值类型为int;
● FloatEvaluator:属性的值类型为float;
● ArgbEvaluator:属性的值类型为十六进制颜色值;
● TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); }}
自定义TypeEvalutor会取代默认的值返回
PropertyValuesHolder
PropertyValuesHolder的效果和AnimatorSet,ViewPropertyAnimator一样:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start(); ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start(); myView.animate().x(50f).y(100f);
TimeInterplator
Time interplator定义了属性值变化的方式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了 TimeInterplator。Interplator继承自TimeInterplator,内部没有任何其他代码。
● AccelerateInterpolator 加速,开始时慢中间加速
● DecelerateInterpolator 减速,开始时快然后减速
● AccelerateDecelerateInterolator 先加速后减速,开始结束时慢,中间加速
● AnticipateInterpolator 反向 ,先向相反方向改变一段再加速播放
● AnticipateOvershootInterpolator 反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
● BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
● CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
● LinearInterpolator 线性,线性均匀改变
● OvershottInterpolator 回弹,最后超出目的值然后缓慢改变到目的值
● TimeInterpolator 一个接口,允许你自定义interpolator,以上几个都是实现了这个接口
当Layout改变时应用动画
ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
ViewGroup.setLayoutTransition(LayoutTransition transition)
transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
● APPEARING 当一个元素在其父元素中变为Visible时对这个元素应用动画
● CHANGE_APPEARING 当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
● DISAPPEARING 当一个元素在其父元素中变为GONE时对其应用动画
● CHANGE_DISAPPEARING 当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间。
3、实际使用
1)ObjectAnimator
①简单使用
ObjectAnimator// .ofFloat(view, "rotationX", 0.0F, 360.0F)// .setDuration(500)// .start();
ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left).start();
②设置背景颜色(View中有setBackgroundColor(@ColorInt int color)方法,所以可以直接使用”backgroundColor”的propertyName):
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", RED, BLUE); colorAnim.setDuration(3000); colorAnim.setEvaluator(new ArgbEvaluator()); colorAnim.setRepeatCount(ValueAnimator.INFINITE); colorAnim.setRepeatMode(ValueAnimator.REVERSE); colorAnim.start();
③多个ObjectAnimator的简单写法:
ObjectAnimator anim1 = ObjectAnimator.ofFloat(balls.get(0), "y", 0f, getHeight() - balls.get(0).getHeight()).setDuration(500); ObjectAnimator anim2 = anim1.clone(); anim2.setTarget(balls.get(1));
④实现一个动画更改多个效果有两种方法:
使用propertyValuesHolder
public void propertyValuesHolder(View view) { PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f); ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start(); }
使用AnimatorSet
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
AnimatorSet 和propertyValuesHolder一起使用:
AnimatorSet set = new AnimatorSet(); set.play( ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left)) .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScaleFinal)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal));
2)自定义propertyName
源码:
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { ObjectAnimator anim = new ObjectAnimator(target, propertyName); anim.setFloatValues(values); return anim; }
target : 执行动画的目标
propertyName : 目标对象中所有的set/get方法,如果需要自定义propertyName,只需要在target的类中添加set方法即可.
propertyName 自定义:
ObjectAnimator animator = ObjectAnimator.ofFloat(CustomView.this, "customPhase", 1.0f, 0.0f); animator.setDuration(10000); animator.start();
//写一个public的方法,set后面的就是propertyName(propertyName第一个字母不需要大写,后面的首字母都需要大写,否则无效).
public void setCustomPhase(float phase) { Log.d("pathview", "setPhase called with:" + String.valueOf(phase)); paint.setPathEffect(createPathEffect(length, phase, 0.0f)); invalidate();// will calll onDraw }
3)自定义Property
源码:
public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property, float... values) { ObjectAnimator anim = new ObjectAnimator(target, property); anim.setFloatValues(values); return anim; }
public CustomProperty(Class<Float> type, String name) { super(type, name); } @Override public Float get(View view) { return 0f; } @Override public void set(View view, Float value) { view.setTranslationX(view.getWidth() * value); view.setTranslationY(view.getHeight() * value); view.setAlpha(value); view.setRotation(360 * value); } } ObjectAnimator animator = ObjectAnimator.ofFloat(btn, new CustomProperty(Float.TYPE, "custom"), 0, 1); animator.setRepeatMode(ObjectAnimator.REVERSE); animator.setRepeatCount(Integer.MAX_VALUE); animator.start();
常用的propertyName:
● translationX and translationY
● rotation, rotationX, and rotationY
● scaleX and scaleY
● pivotX and pivotY
● x and y
● alpha
ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。
当对于属性值,只设置一个的时候,会认为对象该属性的值为开始(getPropName反射获取),然后设置的值为终点。如果设置两个,则一个为开始、一个为结束
动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法
4)ValueAnimator实现动画
不需要操作的对象的属性一定要有getter和setter方法,可以根据当前动画的计算值,来操作任何属性,
public void verticalRun(View view) { ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight()); animator.setTarget(mBlueBall); animator.setDuration(1000).start(); }/** * 自由落体 * @param view */ public void verticalRun( View view) { ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight()); animator.setTarget(mBlueBall); animator.setDuration(1000).start();// animator.setInterpolator(value) animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mBlueBall.setTranslationY((Float) animation.getAnimatedValue()); } }); }/** * 抛物线 * @param view */ public void paowuxian(View view) { ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration(3000); valueAnimator.setObjectValues(new PointF(0, 0)); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.setEvaluator(new TypeEvaluator<PointF>() { // fraction = t / duration @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) { Log.e(TAG, fraction * 3 + ""); // x方向200px/s ,则y方向0.5 * 10 * t PointF point = new PointF(); point.x = 200 * fraction * 3; point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3); return point; } }); valueAnimator.start(); valueAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { PointF point = (PointF) animation.getAnimatedValue(); mBlueBall.setX(point.x); mBlueBall.setY(point.y); } }); }
5)监听动画的事件
每次执行addListener(AnimatorListener listener)方法都会添加一个AnimatorListener到ObjectAnimator中(如果每次都是new AnimatorListener ,那么会添加很多个对象,如果是同一个AnimatorListener ,那么会将它重复添加到ObjectAnimator),所以addListener()方法和new AnimatorListener()不能被重复执行.
public void fadeOut(View view) { ObjectAnimator anim = ObjectAnimator.ofFloat(mBlueBall, "alpha", 0.5f); anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { Log.e(TAG, "onAnimationStart"); } @Override public void onAnimationRepeat(Animator animation) { // TODO Auto-generated method stub Log.e(TAG, "onAnimationRepeat"); } @Override public void onAnimationEnd(Animator animation) { Log.e(TAG, "onAnimationEnd"); ViewGroup parent = (ViewGroup) mBlueBall.getParent(); if (parent != null) parent.removeView(mBlueBall); } @Override public void onAnimationCancel(Animator animation) { // TODO Auto-generated method stub Log.e(TAG, "onAnimationCancel"); } }); anim.start(); }AnimatorListenerAdapter继承了AnimatorListener接口 anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { Log.e(TAG, "onAnimationEnd"); ViewGroup parent = (ViewGroup) mBlueBall.getParent(); if (parent != null) parent.removeView(mBlueBall); } }); ```###6)AnimatorSet的使用//第一:使用playTogether两个动画同时执行,当然还有playSequentially依次执行
public void togetherRun(View view)
{
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, “scaleX”,
1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, “scaleY”,
1.0f, 2f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(2000);
animSet.setInterpolator(new LinearInterpolator());
//两个动画同时执行
animSet.playTogether(anim1, anim2);
animSet.start();
}
“`
//第二:如果我们有一堆动画,如何使用代码控制顺序,比如1,2同时;3在2后面;4在1之前等~就是效果2了
public void playWithAfter(View view) { float cx = mBlueBall.getX(); ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX", 1.0f, 2f); ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY", 1.0f, 2f); ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "x", cx , 0f); ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall, "x", cx); /** * anim1,anim2,anim3同时执行 * anim4接着执行 */ AnimatorSet animSet = new AnimatorSet(); animSet.play(anim1).with(anim2); animSet.play(anim2).with(anim3); animSet.play(anim4).after(anim3); animSet.setDuration(1000); animSet.start(); }
- 关于动画的使用
- 关于动画效果的使用
- 关于Rotate动画使用方式的疑问
- iOS 关于MBProgressHUD的使用 自定义动画
- 安卓中关于属性动画的复合使用
- android关于属性动画的七个使用案例
- Android 加载动画(关于SpinKit的使用)
- SVG-Android开源库——关于动画的使用
- 关于react native 循环动画无法使用InteractionManager的解决办法
- 关于旋转的动画
- 关于动画的总结
- Android 逐帧动画:关于 逐帧动画 的使用都在这里了!
- 关于写动画的心得
- 一些关于动画的资料
- 关于骨骼动画的实现
- 关于UIView动画的制作
- 关于jquery的动画效果
- 关于png动画的问题
- OneToMany字段序列化 failed to lazily initialize a collection of role
- JAXB(三)xsd 验证
- 深度学习与神经网络学习笔记(一)
- 一段html片段,得到其中的某个元素
- Thread--Syn系列(四)线程构造方式
- 关于动画的使用
- Thread--Syn系列(五)
- 我最常用的eclipse快捷方式
- 个人总结7
- Java核心代码(二)ServiceLoader用例
- 百度的标注物没有ID的解决办法
- UI(一)框架介绍
- 百度地图上的标注物太多导致界面卡顿的解决办法
- multi-thread(七)ReentrantReadWriteLock