1.初衷
公司要做一个点餐系统,要求类似要的美团外卖的点餐动画,就像下面这样一个抛物线(biu)
美团的动画
身为一个把时间节约全部投入到工作中的程序员,baidu geogle了好久发现没有这个动画效果的具体实现.有的效果也不是很好,只好自己写一个这样的效果了(搬砖去了)
2.结果
结果demo就是和下面一样做的一个动画效果
自己的动画
可以直接使用拷贝这个类或者在Project中build.gradle添加
allprojects{
repositories{
...
maven{url"https://jitpack.io"}
}
}
在Moudle中的build.gradle
dependencies{
compile'com.github.jlcclidong:AddCartAniamtion:v3.0'
}
直接使用AddCartAniamtion.AddToCart()完成动画,图片默认为填入ImageView的图片,想要自己更改的可以去源码中更改,本人水平有限,希望多交流。
自己使用在RecycleView中没有问题。动画左右飞都木有问题。
3.过程
本身看到过一个用贝塞尔曲线来做这个效果的,效果不好(好吧,主要是自己数学实在不争气)
身为程序员里物理学的最好的还是用物理公式来解决问题吧,加属性动画
首先确定父控件,起始位置控件,以及终点位置控件位置
//计算父控件的位置
int[] parent =new int[2];
rl.getLocationInWindow(parent);//计算起点控件位置
int[] startLocation =new int[2];
startView.getLocationInWindow(startLocation);//计算终点控件位置
int[] endLocation =new int[2];
endView.getLocationInWindow(endLocation);
添加一个用于ImageView用于动画(注意确定添加的位置是一定要注意父控件的Padding值,因为这个错位了好久)
final ImageView view =newImageView(mContext);
//确定ImageView大小与传进来的ImageView相同
RelativeLayout.LayoutParams params =new RelativeLayout.LayoutParams(startView.getWidth(),startView.getHeight());//获取ImageView的图片 并设置在新的ImageView上
view.setImageDrawable(startView.getDrawable());//确定ImageView的位置与startView相同
params.leftMargin= startLocation[0] - parent[0] - rl.getPaddingLeft();
params.topMargin= startLocation[1] - parent[1] - rl.getPaddingTop();rl.addView(view,params);
好吧重点来了 我把初始的X轴Y轴速度设成相同的这样保证了上移的效果 然后根据时间 距离计算初速度 加速度 基本就用到了这么一个公式
s=vt+g*t*t/2
//计算两者的横向X轴的距离差
int XtoX = endLocation[0] - startLocation[0] + endView.getWidth() /2-
startView.getWidth() /2;//根据距离 时间 获取到对应的X轴的初速度
final float xv = XtoX / time;//计算两者的横向X轴的距离差
int YtoY = endLocation[1] - startLocation[1];//根据距离 时间 初始设置的Y轴初速度与X轴初速度相同 获取到竖直方向上的加速度
final float g;
if(xv>0) {g = (YtoY + xv * time) / time / time *2;
}else{
g = (YtoY - xv * time) / time / time *2;
}
设置属性动画了
ValueAnimator va =new ValueAnimator();
va.setDuration(time *1000);
va.setObjectValues(newPointF(0,0));//计算位置
va.setEvaluator(new TypeEvaluator() {
@Override
publicPointFevaluate(float v,PointF pointF,PointF t1) {
PointF point =newPointF();
point.x= v *xv*time;
if(xv>0) {
point.y=g* (v *time) * (v *time) /2-xv* v *time;
}else{
point.y=g* (v *time) * (v *time) /2+xv* v *time;
}
return point;
}
});
//设置动画
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
PointF point = (PointF)valueAnimator.getAnimatedValue();
view.setTranslationX(point.x);
view.setTranslationY(point.y);
}
});
设置成功 开启动画 最后监听动画结束时remove这个ImageView
4.结束语
写逻辑代码写的久了很多时候就会忘了一般的动画实现,这个动画实现虽然没什么含金量,但是很多项目中都可能会用得到可以直接使用还是很方便的,大神掠过,新接触android动画的还是可以看看的,代码内注释很详细。