常见的动画分为:
-补间动画
-帧动画
- 属性动画
学完这个分享自己项目一个简单的动画:
转场动画:这个是谷歌提供的样式!下面自己模仿了一下。
模仿谷歌设计来自己做了一个。
对于学过flash动画的人来说补间动画很好理解的,因为动画开始和结尾的中间过程都是假象,是渲染出来的表象,只是显示的位置变动,View的实际位置未改变,表现为View移动到其他地方,点击事件仍在原处才能响应。
补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、透明度(AlphaAnimation)四个子类。
补间动画在android里面支持xml来设置或者java代码设置。
常见的布局动画类如下:
translate属性 | TranslateAnimation | 含义 |
---|---|---|
android:fromXDelta | TranslateAnimation translateAnimation=TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta); | 平移起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:fromYDelta | 同上 | 同理fromXDelta |
android:toXDelta | 同上 | 平移终点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点) |
android:toYDelta | 同上 | 同上 |
android:fillAfter | translateAnimation.setFillAfter(true); | 动画显示结束保持最后一帧 |
android:duration | translateAnimation.setDuration(3000); | 动画执行的时间 |
android:repeatCount | translateAnimation.setRepeatCount(TranslateAnimation.INFINITE); | 动画执行的次数可以是整数或者infinite为无限循环执行动画 |
使用如下:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="-100%"
android:fillAfter="true"
android:duration="1000"
>
translate>
Alpha属性 | AlphaAnimation | 含义 |
---|---|---|
android:fromAlpha | AlphaAnimation alphaAnimation=new AlphaAnimation(float fromAlpha, float toAlpha); | 是View视图起始透明度,透明度是0-1 |
android:toAlpha | 同上 | 结束时的透明度 |
android:fillAfter | alphaAnimation.setFillAfter(true); | 动画显示结束保持最后一帧 |
android:duration | alphaAnimation.setDuration(3000); | 动画执行的时间 |
android:repeatCount | alphaAnimation.setRepeatCount(TranslateAnimation.INFINITE); | 动画执行的次数可以是整数或者infinite为无限循环执行动画 |
使用如下:
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1"
android:toAlpha="0.5"
android:fillAfter="true"
android:duration="3000"
>
alpha>
RotateAnimation 属性 | RotateAnimation | 含义 |
---|---|---|
android:fromDegrees | RotateAnimation rotateAnimation=RotateAnimation(float fromDegrees, float toDegrees); | 是View视图起始角度 |
android:toDegrees | 同上 | 结束时的角度 |
android:fillAfter | rotateAnimation.setFillAfter(true); | 动画显示结束保持最后一帧 |
android:duration | rotateAnimation.setDuration(3000); | 动画执行的时间 |
android:repeatCount | rotateAnimation.setRepeatCount(TranslateAnimation.INFINITE); | 动画执行的次数可以是整数或者infinite为无限循环执行动画 |
使用如下:
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="90"
android:fillAfter="true"
android:duration="3000"
>
rotate>
ScaleAnimation属性 | ScaleAnimation | 含义 |
---|---|---|
android:fromXScale | ScaleAnimation scaleAnimation=ScaleAnimation(float fromX, float toX, float fromY, float toY) | 这个相信能看懂。 |
android:toXScale | 同上 | 结束时的位置 |
android:fillAfter | scaleAnimation.setFillAfter(true); | 动画显示结束保持最后一帧 |
android:duration | scaleAnimation.setDuration(3000); | 动画执行的时间 |
android:repeatCount | scaleAnimation.setRepeatCount(TranslateAnimation.INFINITE); | 动画执行的次数可以是整数或者infinite为无限循环执行动画 |
使用如下:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.5"
android:toXScale="1"
android:fromYScale="0.5"
android:toYScale="1"
android:fillAfter="true"
android:duration="3000"
>
scale>
当然了有动画集合这个类了。使用也是很简单的:
set.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
android:shareInterpolator="true"
android:repeatMode="reverse"
>
<scale
android:duration="1000"
android:fillAfter="true"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:toXScale="1"
android:toYScale="1"
android:repeatCount="infinite"/>
<alpha
android:duration="2000"
android:fillAfter="true"
android:fromAlpha="0.7"
android:toAlpha="1"/>
<rotate
android:fromDegrees="0"
android:toDegrees="90"
android:fillAfter="true"
android:duration="1000"
/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="-100%"
android:fillAfter="true"
android:duration="2000"
/>
set>
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
//位移动画
Animation animation= AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate);
button.setAnimation(animation);
TranslateAnimation translateAnimation=new TranslateAnimation(0,200,0,200);
AlphaAnimation translateAnimation=new AlphaAnimation(0.5f,1f);
translateAnimation.setDuration(3000);
translateAnimation.setRepeatMode(TranslateAnimation.INFINITE);
translateAnimation.setRepeatCount(TranslateAnimation.INFINITE);
translateAnimation.setFillAfter(true);
*/
/*
//渐变动画
AlphaAnimation alphaAnimation=new AlphaAnimation(0.5f,1f);
alphaAnimation.setDuration(3000);
alphaAnimation.setRepeatMode(TranslateAnimation.INFINITE);
alphaAnimation.setRepeatCount(TranslateAnimation.INFINITE);
alphaAnimation.setFillAfter(true);
button.startAnimation(alphaAnimation);*/
/*
* //旋转动画
* public RotateAnimation(float fromDegrees, float toDegrees) {
*
RotateAnimation rotateAnimation=new RotateAnimation(0,90);
rotateAnimation.setDuration(3000);
rotateAnimation.setRepeatMode(TranslateAnimation.INFINITE);
rotateAnimation.setRepeatCount(TranslateAnimation.INFINITE);
rotateAnimation.setFillAfter(true);
button.startAnimation(rotateAnimation);*/
/*
* 缩放动画
*
*
ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 0.7f, 0.5f, 0.7f);
scaleAnimation.setDuration(3000);
scaleAnimation.setRepeatMode(TranslateAnimation.INFINITE);
scaleAnimation.setRepeatCount(TranslateAnimation.INFINITE);
scaleAnimation.setFillAfter(true);
button.startAnimation(scaleAnimation); */
AlphaAnimation alphaAnimation=new AlphaAnimation(0.5f,1f);
alphaAnimation.setDuration(3000);
alphaAnimation.setRepeatMode(TranslateAnimation.INFINITE);
alphaAnimation.setRepeatCount(TranslateAnimation.INFINITE);
alphaAnimation.setFillAfter(true);
button.startAnimation(alphaAnimation);
RotateAnimation rotateAnimation=new RotateAnimation(0,90);
rotateAnimation.setDuration(3000);
rotateAnimation.setRepeatMode(TranslateAnimation.INFINITE);
rotateAnimation.setRepeatCount(TranslateAnimation.INFINITE);
rotateAnimation.setFillAfter(true);
button.startAnimation(rotateAnimation);
ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 0.7f, 0.5f, 0.7f);
scaleAnimation.setDuration(3000);
scaleAnimation.setRepeatMode(TranslateAnimation.INFINITE);
scaleAnimation.setRepeatCount(TranslateAnimation.INFINITE);
scaleAnimation.setFillAfter(true);
button.startAnimation(scaleAnimation);
//动画集合
AnimationSet animationSet=new AnimationSet(true);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.setDuration(2000);
animationSet.setRepeatMode(AnimationSet.INFINITE);
animationSet.setRepeatCount(AnimationSet.INFINITE);
button.setAnimation(animationSet);
}
});
缩放,淡入淡出,滑进滑出….很多由你来设置:这里为了演示效果设置时间很长。用时候可以设置短。
如下图:第一个页面跳转第二个Activity页面动画效果:
这里在demon里面activity跳转动画都写了好多开参考。
可能很多人不明白100%p和100%这样的问题。明确知道左下角为坐标原点。看看别人的博客就懂了
如上图:Activity A从-100%p滑到0即从位置一滑到位置二。很简单的理解。看图就知道了。
由于3.0之前的View动画太过单一,不能够满足开发和用户,所以谷歌在3.0之后提出了属性动画
,属性动画是从3.0及以后出现的(如果要兼容低版本,可以使用一个民间版第三方的一个jar NineOldAndroid.jar,用法跟系统的用法差不多)。不断地控制控件的属性变化达到动画的效果,一般我们是一些组合的属性动画达到复杂的效果。
使用1:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, "translationX", 0f, 300f);
objectAnimator.setDuration(4000);
objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator.start();
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(view, "translationY", 0f, 300f);
objectAnimator1.setDuration(7000);
objectAnimator1.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator1.start();
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(view, "scaleX", 0.2f, 1f);
objectAnimator2.setDuration(6000);
objectAnimator2.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator2.start();
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(view, "scaleY", 0.2f, 1f);
objectAnimator3.setDuration(6000);
objectAnimator3.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator3.start();
ObjectAnimator objectAnimator4=ObjectAnimator.ofFloat(view,"alpha",0.5f,1f);
objectAnimator4.setDuration(6000);
objectAnimator4.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator4.start();
使用2:
ObjectAnimator animator = ObjectAnimator.ofFloat(button, "haha", 0f, 100f);//没有这个属性的时候,就是valueanimator
animator.setDuration(300);
//设置动画监听
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//动画在执行的过程当中,不断地调用此方法
// animation.getAnimatedFraction()//百分比
//得到duration时间内 values当中的某一个中间值。0f~100f
float value = (float) animation.getAnimatedValue();//
button.setScaleX(0.5f+value/200);//0.5~1
button.setScaleY(0.5f+value/200);//0.5~1
}
});
animator.start();
使用3:
ValueAnimator valueAnimator=ValueAnimator.ofFloat(0f,200f);
valueAnimator.setDuration(200);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// //动画在执行的过程当中,不断地调用此方法
//// animation.getAnimatedFraction()//百分比
// //得到duration时间内 values当中的某一个中间值。0f~100f
float value = (float) animation.getAnimatedValue();//
button.setScaleX(0.5f + value / 200);//0.5~1
button.setScaleY(0.5f + value / 200);//0.5~1
}
});
valueAnimator.start();
使用4:
//3)方法3
//float... values:代表关键帧的值
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 1f,0.7f,1f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f,0.7f,1f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f,0.7f,1f);
// PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("translationX", 0f,300f);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(button, holder1,holder2,holder3);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
float animatedValue = (float) animation.getAnimatedValue();
float animatedFraction = animation.getAnimatedFraction();
long playTime = animation.getCurrentPlayTime();
System.out.println("animatedValue:"+animatedValue+", playTime:"+playTime);
}
});
animator.start();
动画集合:
//4)方法4:-----------------动画集合--------------------
ObjectAnimator animator1 = ObjectAnimator.ofFloat(button,"alpha", 1f,0.7f,1f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(button,"scaleX", 1f,0.7f,1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(button,"scaleY", 1f,0.7f,1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
// animatorSet.play(anim);//执行当个动画
// animatorSet.playTogether(animator1,animator2,animator3);//同时执行
animatorSet.playSequentially(animator1,animator2,animator3);//依次执行动画
animatorSet.start();
实现一个抛物线:
首先抛物线方程:水平方向:x:匀速运动:
竖着方向:y=1/2*g*t*t
ValueAnimator valueAnimator=new ValueAnimator();
valueAnimator.setDuration(4000);
valueAnimator.setObjectValues(new PointF(0,0));//起点坐标
//估值器:====定义计算规则
valueAnimator.setEvaluator(new TypeEvaluator() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
//拿到每一个时间点的坐标:
//x
PointF pointF=new PointF();
//x=vt
pointF.x=100f*fraction*4;//初始速度*执行的百分比
pointF.y=0.5f*100f*(fraction*4)*(fraction*4);//为了30明显我把g设置成
return pointF;
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//得到此事件点的坐标
PointF pointF= (PointF) animation.getAnimatedValue();
button.setX(pointF.x);
button.setY(pointF.y);
}
});
valueAnimator.start();
案例代码:
//2017年11月10日:实现点击旋转动画这个有点小复杂
ibTop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isWmflag) {//如果是女生
if (count % 2 == 0 && endOther) {//如果在人体前面进行点击旋转进行旋转动画且切换图片哦
endOther = false;
ObjectAnimator oa = ObjectAnimator.ofFloat(home_man_iv, "rotationY",
new float[]{0f, 60f, 120f, 180f});
oa.setDuration(1000);
oa.setRepeatCount(0);
oa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//这个值是获取对应的什么时间进行切换图片。首先设置了0f,60f,120f,180f这四个插入值作为旋转角度,当90度时候我们来切换背景图片达到旋转切换。
float playTime = (float) animation.getAnimatedValue();
if (playTime >= 90) {
home_man_iv.setBackgroundResource(R.drawable.female_b);
}
//当180度时候我们进行标记。这个旋转结束了。可以点击进行下一个动画了。endOther作为标记。
if (playTime == 180f) {
count++;
endOther = true;
}
}
});
oa.start();
} else if (endOther) {//如果是女生
endOther = false;
ObjectAnimator oa = ObjectAnimator.ofFloat(home_man_iv, "rotationY",
new float[]{0f, 60f, 120f, 180f});
oa.setDuration(1000);
oa.setRepeatCount(0);
oa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float playTime = (float) animation.getAnimatedValue();
if (playTime >= 90) {
home_man_iv.setBackgroundResource(R.drawable.female_f);
}
if (playTime == 180f) {
count++;
endOther = true;
}
}
});
oa.start();
}
} else {
if (count % 2 == 0 && endOther) {
endOther = false;
ObjectAnimator oa = ObjectAnimator.ofFloat(home_man_iv, "rotationY",
new float[]{0f, 60f, 120f, 180f});
oa.setDuration(1000);
oa.setRepeatCount(0);
oa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float playTime = (float) animation.getAnimatedValue();
if (playTime >= 90) {
home_man_iv.setBackgroundResource(R.drawable.male_b);
}
if (playTime == 180f) {
count++;
endOther = true;
}
}
});
oa.start();
} else if (endOther) {
endOther = false;
ObjectAnimator oa = ObjectAnimator.ofFloat(home_man_iv, "rotationY",
new float[]{0f, 60f, 120f, 180f});
oa.setDuration(1000);
oa.setRepeatCount(0);
oa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float playTime = (float) animation.getAnimatedValue();
if (playTime >= 90) {
home_man_iv.setBackgroundResource(R.drawable.male_f);
}
if (playTime == 180f) {
count++;
endOther = true;
}
}
});
oa.start();
}
}
}
});
转场动画:
ActivityOptions类作为谷歌提供的转场效果类如果用过的很简单哦。
首先xml里面用android:transitionName作为标记给共享的view。
下面recylerView里面item中item
<ImageView
android:transitionName="ivtraname"
android:id="@+id/item_iv"
android:layout_width="match_parent"
android:layout_height="180dp"/>
这个是跳转后的布局里面:
<ImageView
android:background="@mipmap/rv0"
android:transitionName="ivtraname"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
sharedElement是ImageView共享View
sharedElementName=tansitionName的名称=ivtraname
public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
View sharedElement, String sharedElementName) {
return makeSceneTransitionAnimation(activity, Pair.create(sharedElement, sharedElementName));
}
@SafeVarargs
public static ActivityOptions makeSceneTransitionAnimation(Activity activity,
Pair... sharedElements) {
使用也是很简单的:这里我使用的是兼容包类
ActivityOptionsCompat optionsCompat1 = ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context,(View)holder.miv,"ivtraname");
Intent intent = new Intent(context, Main3Activity.class);
context.startActivity(intent, optionsCompat1.toBundle());//最低兼容16
效果如下:
demon地址如下:
https://github.com/luhenchang/Lsn22_SceneTransitionAnimation.git
如果有所不对地方请多多指教,相互学习!!!!
https://github.com/luhenchang/Lsn20_PropertyAnimation.git