属性动画
DEMO地址:/chaozhouzhang/CustomProgressView
1、值动画 ValueAnimator
值动画具体实现步骤:
*属性动画之值动画: *1、指定动画数值区间 *2、指定插值器,定义动画数值的进度变化规律 *3、指定估值器,根据插值器的进度变化规律,计算具体的动画数值 *4、设置监听器,监听估值器返回的具体动画数值,然后根据此具体数值,来对控件做出属性变化的设置操作 *//**
使用值动画,实现抛物动画:
animator.addUpdateListener(newValueAnimator.AnimatorUpdateListener(){ @Override publicvoidonAnimationUpdate(ValueAnimatoranimation){ mPoint=(Point)animation.getAnimatedValue(); mIvBall.layout(mPoint.x,mPoint.y,mPoint.x+mIvBall.getWidth(),mPoint.y+mIvBall.getHeight()); } }); animator.setDuration(2000); animator.start();ValueAnimatoranimator=ValueAnimator.ofObject(newFallingBallEvaluator(),newPoint(0,0),newPoint(500,500));
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/value/FallingBallValueActivity.java
2、对象动画 ObjectAnimator
对象动画具体实现步骤:
*属性动画之对象动画: *1、指定动画数值区间以及属性和控件 *2、指定插值器,定义动画数值的进度变化规律 *3、指定估值器,根据插值器的进度变化规律,计算具体的动画数值 *4、系统自定调用控件的set方法,根据属性拼装set方法并反射调用,并将当前值作为参数传入 *//**
自定义ImageView:
publicFallingImageView(Contextcontext){ super(context); } publicFallingImageView(Contextcontext,AttributeSetattrs){ super(context,attrs); } publicFallingImageView(Contextcontext,AttributeSetattrs,intdefStyleAttr){ super(context,attrs,defStyleAttr); } /** *对象动画会使用反射自动调用此set方法 *@parampoint */ publicvoidsetFallingPos(Pointpoint){ layout(point.x,point.y,point.x+getWidth(),point.y+getHeight()); } /** *当指定一个动画值时,动画会通过get方法来获取初始值,否则会崩溃 *@return */ publicPointgetFallingPos(){ returnnewPoint(0,0); } }publicclassFallingImageViewextendsandroidx.appcompat.widget.AppCompatImageView{
使用值动画,实现抛物动画:
objectAnimator.setDuration(2000); objectAnimator.start();ObjectAnimatorobjectAnimator=ObjectAnimator.ofObject(mIvBall,"fallingPos",newFallingBallEvaluator(),newPoint(0,0),newPoint(500,500));
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/object/FallingBallObjectActivity.java
3、动画集合 AnimatorSet
使用动画集合实现菜单动画:
开:
//每一份角度 doubledegree=Math.toRadians(90)/(totalIndex-1)*currIndex; //X轴移动距离 inttranslationX=-(int)(radius*Math.sin(degree)); //Y轴移动距离 inttranslationY=-(int)(radius*Math.cos(degree)); AnimatorSetanimatorSet=newAnimatorSet(); ObjectAnimatorobjectAnimatorTranslationX=ObjectAnimator.ofFloat(view,"translationX",0,translationX); ObjectAnimatorobjectAnimatorTranslationY=ObjectAnimator.ofFloat(view,"translationY",0,translationY); ObjectAnimatorobjectAnimatorScaleX=ObjectAnimator.ofFloat(view,"ScaleX",0F,1F); ObjectAnimatorobjectAnimatorScaleY=ObjectAnimator.ofFloat(view,"ScaleY",0F,1F); ObjectAnimatorobjectAnimatorAlpha=ObjectAnimator.ofFloat(view,"alpha",0F,1F); animatorSet.playTogether(objectAnimatorTranslationX,objectAnimatorTranslationY,objectAnimatorScaleX,objectAnimatorScaleY,objectAnimatorAlpha); animatorSet.setDuration(500); animatorSet.start(); }privatevoidmenuOpen(Viewview,intcurrIndex,inttotalIndex,intradius){
关:
//每一份角度 doubledegree=Math.PI*currIndex/((totalIndex-1)*2); //X轴移动距离 inttranslationX=-(int)(radius*Math.sin(degree)); //Y轴移动距离 inttranslationY=-(int)(radius*Math.cos(degree)); AnimatorSetanimatorSet=newAnimatorSet(); ObjectAnimatorobjectAnimatorTranslationX=ObjectAnimator.ofFloat(view,"translationX",translationX,0); ObjectAnimatorobjectAnimatorTranslationY=ObjectAnimator.ofFloat(view,"translationY",translationY,0); ObjectAnimatorobjectAnimatorScaleX=ObjectAnimator.ofFloat(view,"ScaleX",1F,0F); ObjectAnimatorobjectAnimatorScaleY=ObjectAnimator.ofFloat(view,"ScaleY",1F,0F); ObjectAnimatorobjectAnimatorAlpha=ObjectAnimator.ofFloat(view,"alpha",1F,0F); animatorSet.playTogether(objectAnimatorTranslationX,objectAnimatorTranslationY,objectAnimatorScaleX,objectAnimatorScaleY,objectAnimatorAlpha); animatorSet.setDuration(500); animatorSet.start(); }privatevoidmenuClose(Viewview,intcurrIndex,inttotalIndex,intradius){
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/set/MenuActivity.java
4、属性值与关键帧 PropertyValuesHolder Keyframe
*关键帧,为了方便控制动画速率,表示某个时间点应该在某个位置上 *视频,1秒要播24帧图片 *一个关键帧的两个元素:时间点和位置 *fraction动画进度 *value对应动画进度的动画数值 *KeyFrame可以设置插值器,默认使用线性插值器 *可以做电话响铃的动画,一张电话图片,11张关键帧 *//**
使用属性值和关键帧实现电话铃响动画:
Keyframekeyframe1=Keyframe.ofFloat(0f,0); Keyframekeyframe2=Keyframe.ofFloat(0.1f,-20f); Keyframekeyframe3=Keyframe.ofFloat(0.2f,20f); Keyframekeyframe4=Keyframe.ofFloat(0.3f,-20f); Keyframekeyframe5=Keyframe.ofFloat(0.4f,20f); Keyframekeyframe6=Keyframe.ofFloat(0.5f,-20f); Keyframekeyframe7=Keyframe.ofFloat(0.6f,20f); Keyframekeyframe8=Keyframe.ofFloat(0.7f,-20f); Keyframekeyframe9=Keyframe.ofFloat(0.8f,20f); Keyframekeyframe10=Keyframe.ofFloat(0.9f,-20f); Keyframekeyframe11=Keyframe.ofFloat(1.0f,0f); PropertyValuesHolderpropertyValuesHolder=PropertyValuesHolder.ofKeyframe("rotation", keyframe1,keyframe1,keyframe2,keyframe3,keyframe4,keyframe5, keyframe6,keyframe7,keyframe8,keyframe9,keyframe10,keyframe11); //缩放效果X KeyframekeyframeScaleX0=Keyframe.ofFloat(0,1f); KeyframekeyframeScaleX1=Keyframe.ofFloat(0.1f,1.1f); KeyframekeyframeScaleX9=Keyframe.ofFloat(0.9f,1.1f); KeyframekeyframeScaleX10=Keyframe.ofFloat(1f,1f); PropertyValuesHolderpropertyValuesHolderScaleX=PropertyValuesHolder.ofKeyframe("ScaleX", keyframeScaleX0,keyframeScaleX1,keyframeScaleX9,keyframeScaleX10); //缩放效果Y KeyframekeyframeScaleY0=Keyframe.ofFloat(0,1f); KeyframekeyframeScaleY1=Keyframe.ofFloat(0.1f,1.1f); KeyframekeyframeScaleY9=Keyframe.ofFloat(0.9f,1.1f); KeyframekeyframeScaleY10=Keyframe.ofFloat(1f,1f); PropertyValuesHolderpropertyValuesHolderScaleY=PropertyValuesHolder.ofKeyframe("ScaleY", keyframeScaleY0,keyframeScaleY1,keyframeScaleY9,keyframeScaleY10); ObjectAnimatorobjectAnimator=ObjectAnimator.ofPropertyValuesHolder(mIvPhone, propertyValuesHolder,propertyValuesHolderScaleX,propertyValuesHolderScaleY); objectAnimator.setDuration(1000); objectAnimator.start();//旋转效果,左右震动
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/advanced/PhoneActivity.java
5、布局动画 LayoutTransition
* LayoutTransition.APPEARING;新元素在容器中出现时的动画; * LayoutTransition.CHANGE_APPEARING;容器中显示新元素,其他元素需要变化时的动画; * LayoutTransition.CHANGE_DISAPPEARING;容器中移除旧元素,其他元素需要变化时的动画; *LayoutTransition.CHANGING; * LayoutTransition.DISAPPEARING;旧元素在容器中移除时的动画; *//**
实现移除布局内控件的动画:
*设置移除容器内图片控件时候的动画 */ LayoutTransitionlayoutTransition=newLayoutTransition(); ObjectAnimatorobjectAnimator=ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f); layoutTransition.setAnimator(LayoutTransition.DISAPPEARING,objectAnimator); /** *设置动画间的间隔 */ layoutTransition.setStagger(LayoutTransition.DISAPPEARING,1000); mClLayoutTransition.setLayoutTransition(layoutTransition);/**
*移除布局 */ mClLayoutTransition.removeView(mIvTest);/**
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/advanced/ViewGroupAnimateActivity.java
6、估值器 Evaluator
自定义估值器,实现类型估值器TypeEvaluator,并传入泛型的具体类型。 扩展: 自定义插值器,实现时间插值器TimeInterpolator后,实现获取插值Interpolation的方法,也可以直接实现插值器Interpolator,因为Interpolator继承的是时间插值器TimeInterpolator。估值器,根据插值器的数值进度变化规律,计算出具体的动画数值。
自定义估值器:
/** *@paramfraction插值器中的进度返回值 *@paramstartValue动画数值区间的起始数值 *@paramendValue动画数值区间的结束数值 *@return估值器返回给监听器的具体动画数值 */ @Override publicIntegerevaluate(floatfraction,IntegerstartValue,IntegerendValue){return(int)(endValue-fraction*(endValue-startValue)); } }publicclassReverseEvaluatorimplementsTypeEvaluator{
DEMO地址:/chaozhouzhang/CustomProgressView/blob/master/CustomProgressView/app/src/main/java/androidstack/progress/animation/property/evaluator/ReverseEvaluator.java
欢迎关注微信公众号,Android技术堆栈: