一、引入
- 其实之前一直以为像饿了么或者是美团外卖那种把商品添加到购物车的动画会很难做,但是实际做起来好像并没有想象中的那么难哈哈。
- 布局主要使用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout+TabLayout+ViewPager
- 动画主要使用二阶贝塞尔曲线与属性动画
- 消息传递使用EventBus普通事件
二、大致思路
如图所示主要有三个点,起点、终点、以及贝塞尔曲线的控制点
起点即点击的View的位置,一般来说用如下方式即可取得。
startPosition[0]
为x轴开始坐标,startPosition[1]
为Y轴终点坐标,两点可以看作对角线上面的两个端点(左上角x坐标,右下角y坐标)1
2
3//贝塞尔起始数据点
int[] startPosition = new int[2];
view.getLocationOnScreen(startPosition);终点即购物车篮子的位置,与起点类似
1
mShoppingCart.getLocationInWindow(endPosition);
控制点,我选的控制点为上图的C点,即A点的y坐标,B点的X坐标
1
2controlPosition[0] = endPosition[0];
controlPosition[1] = startPosition[1];需要注意的地方,我不清楚是不是因为我的布局的问题,获取到的点击的A点总是会有一个偏移,后来经同事提醒,减去了TabLayout的坐标的y轴坐标即位置才可以。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 起点
int[] startPosition;
// 终点
int[] endPosition = new int[2];
// 贝塞尔控制点
int[] controlPosition = new int[2];
// tablayout位置
int[] tablayoutPosition = new int[2];
startPosition = data.getStartPosition();
mShoppingCart.getLocationInWindow(endPosition);
mTabLayout.getLocationInWindow(tablayoutPosition);
// 处理起点y坐标偏移的问题
startPosition[1] = startPosition[1] - tablayoutPosition[1] - mTabLayout.getHeight();
// 终点进行一下居中处理
endPosition[0] = endPosition[0] + (mShoppingCart.getWidth() / 2);
controlPosition[0] = endPosition[0];
controlPosition[1] = startPosition[1];通过
Path
的quadTo
方法绘制贝塞尔曲线,使用PathMeasure
获取点的坐标(借助ValueAnimator.ofFloat()
配合getPosTan()
来获取坐标)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Path path = new Path();
path.moveTo(startPosition[0], startPosition[1]);
path.quadTo(controlPosition[0], controlPosition[1], endPosition[0], endPosition[1]);
PathMeasure pathMeasure = new PathMeasure();
// false表示path路径不闭合
pathMeasure.setPath(path, false);
// ofFloat是一个生成器
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, pathMeasure.getLength());
// 匀速线性插值器
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setDuration(800);
valueAnimator.addUpdateListener(animation -> {
float value = (Float) animation.getAnimatedValue();
pathMeasure.getPosTan(value, currentPosition, null);
imageView.setX(currentPosition[0]);
imageView.setY(currentPosition[1]);
});
valueAnimator.start();下面是用属性动画给购物车篮子做了一个放大缩小的动画效果
1
2
3
4
5
6
7
8
9
10
11// mShoppingCart是View
ObjectAnimator shoppingCartX = ObjectAnimator.ofFloat(mShoppingCart, "scaleX", 1.0f, 1.3f, 1.0f);
ObjectAnimator shoppingCartY = ObjectAnimator.ofFloat(mShoppingCart, "scaleY", 1.0f, 1.3f, 1.0f);
shoppingCartX.setInterpolator(new AccelerateInterpolator());
shoppingCartY.setInterpolator(new AccelerateInterpolator());
AnimatorSet shoppingCart = new AnimatorSet();
shoppingCart
.play(shoppingCartX)
.with(shoppingCartY);
shoppingCart.setDuration(800);
shoppingCart.start();
三、稍完整的大部分代码
1 | private void AddAnimation(AddEventBean data) { |
四、大致写下布局(同时也算留做备份)
1 |
|