动画效果收集

一些动画效果的收集,有空进行实践并进行改良。一部分的驱动力是需求项目需要对应的动画,直接能使用更好,关键是需要自己改源码自定义。

Activity分割动画

通过使用,发现下列问题:

  • 不能获取rootview,总是有一部分没有获取到
  • 没有相反的后退动画。分割后进入,后退合并。

于是进行改良:查看ActivitySplitAnimationUtil.java

字体滚动改变

参考:Android 实现滚动数字的TextView

其实关键是ObjectAnimtor的使用的参数propertyName=number

仿蘑菇街加入购物车效果

通过观察动画可知道其实现原理和步骤为:

  • 通过对imageviewwbitmap生成另一个imageview即中心的小圆形图片并布置在中间
  • 对此view先进行放大2倍然后在变回原来的1倍
  • 抛物线的效果+alpha变消失。

理解了整个原理,那么就好办了。下面直接提供代码:

为根布局添加新的imgeview:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ViewGroup rootVG=(ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content);//获取根布局,晚上搜索下。

//下面过程是获取点击iamgeview的bitmap资源,不按下面获取bitmap写会发生无法强转成BitmapDrawable的错误
Bitmap productBmp = null;
Drawable drawable = imgTmp.getDrawable();
if (drawable instanceof BitmapDrawable) {
productBmp = ((BitmapDrawable) drawable).getBitmap();
} else {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
productBmp = bitmap;
}

//将bitmap转化成圆形的资源
RoundedBitmapDrawable roundDrawable= RoundedBitmapDrawableFactory.create(activity.getResources(),productBmp);
roundDrawable.setCircular(true);
final ImageView imageView=new ImageView(activity);
imageView.setImageDrawable(roundDrawable);

//设置布局,根据系统加载布局的原理,最终的根布局是一个frameLayout来的,直接使用FrameLayout进行设置即可。
FrameLayout.LayoutParams fLayoutParams=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
fLayoutParams.gravity=Gravity.CENTER;

rootVG.addView(imageView,fLayoutParams);

属性动画先放大再缩小到原理,结合AnimSet,在动画结束的时候执行水平自由落体运动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ObjectAnimator scaleX= ObjectAnimator.ofFloat(imageView,"scaleX",1f,2f,1f);
ObjectAnimator scaleY=ObjectAnimator.ofFloat(imageView,"scaleY",1f,2f,1f);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(scaleX,scaleY);
animatorSet.setInterpolator(new BounceInterpolator());
animatorSet.setDuration(1000);
animatorSet.start();
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
ValueAnimator valueAnimator=getParrabolaAnim(imageView,imageView.getLeft(),imageView.getTop(),0,0);
valueAnimator.start();
}
});

水平自由落体运动的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private ValueAnimator getParrabolaAnim(final View view, final float originX, final float originY, float targetX, float targetY){
ValueAnimator valueAnimator=new ValueAnimator();
valueAnimator.setObjectValues(new PointF(targetX,targetY));
valueAnimator.setInterpolator(new AccelerateInterpolator());
valueAnimator.setDuration(1000);
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
int speed=(int) originX;
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF pointF=new PointF();
//x轴的运动,y轴的自由落体运动最终的值是等于目标值的距离,也就是对应的坐标
float fx=originX-speed*fraction;
float fy=originY-0.5f*2*originY*fraction*fraction;
pointF.x=fx<=endValue.x?endValue.x:fx;
pointF.y=fy<=endValue.y?endValue.y:fy;
return pointF;
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF point = (PointF) animation.getAnimatedValue();
view.setX(point.x);
view.setY(point.y);
view.setAlpha(point.y/originY);
}
});
return valueAnimator;
}

关键在于evaluate方法关于计算自由落体的运动: