目录
书接上文,我们接着说。如果你没有看 购物车完整效果(上),这篇博客的话,建议先从上篇博客看。
添加商品时的抛物线动画
文章中,第一个效果图的抛物线效果,源码中也都有的,关键代码如下:
/**
* 抛物线动画
*
* @param addView 动画开始的控件view
* @param shoppingCartView 动画结束的控件view
*/
private void startAnimation(View addView, View shoppingCartView) {
int[] addLocation = new int[2];
int[] cartLocation = new int[2];
int[] recycleLocation = new int[2];
addView.getLocationInWindow(addLocation);
shoppingCartView.getLocationInWindow(cartLocation);
mContentRecyclerView.getLocationInWindow(recycleLocation);
PointF startP = new PointF();
PointF endP = new PointF();
PointF controlP = new PointF();
//这个间距要和自定义AnimShopButton 中默认的一致
float betweenCircle = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 34, getResources().getDisplayMetrics());
startP.x = addLocation[0] + betweenCircle;
//startP.x = addLocation[0];
startP.y = addLocation[1] - recycleLocation[1];
endP.x = cartLocation[0];
endP.y = cartLocation[1] - recycleLocation[1];
controlP.x = endP.x;
controlP.y = startP.y;
final FakeAddImageView fakeAddImageView = new FakeAddImageView(this);
mainLayout.addView(fakeAddImageView);
fakeAddImageView.setImageResource(R.drawable.ic_bug_cart);
fakeAddImageView.getLayoutParams().width = getResources().getDimensionPixelSize(R.dimen.height_20);
fakeAddImageView.getLayoutParams().height = getResources().getDimensionPixelSize(R.dimen.height_20);
fakeAddImageView.setVisibility(View.VISIBLE);
ObjectAnimator addAnimator = ObjectAnimator.ofObject(fakeAddImageView, "mPointF",
new PointFTypeEvaluator(controlP), startP, endP);
addAnimator.setInterpolator(new AccelerateInterpolator());
addAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
fakeAddImageView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animator) {
fakeAddImageView.setVisibility(View.GONE);
mainLayout.removeView(fakeAddImageView);
totalPriceCalculation();//当动画结束之后,在更新数量
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
ObjectAnimator scaleAnimatorX = new ObjectAnimator().ofFloat(shoppingCartView, "scaleX", 0.6f, 1.0f);
ObjectAnimator scaleAnimatorY = new ObjectAnimator().ofFloat(shoppingCartView, "scaleY", 0.6f, 1.0f);
scaleAnimatorX.setInterpolator(new AccelerateInterpolator());
scaleAnimatorY.setInterpolator(new AccelerateInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(scaleAnimatorX).with(scaleAnimatorY).after(addAnimator);
animatorSet.setDuration(800);
animatorSet.start();
}
底部弹出购物车清单
这里用的是 bottomsheet 这个开源库。用法不再废话了,关键代码:
/*底部弹框 购物车 相关 stat */
private void showPopupWindow(List<ShopCartBean> shopCartBeans) {
//if (bottomSheet == null) {
View bottomSheet = createBottomSheetView(shopCartBeans);//底层视图初始化
// }
if (bottomSheetLayout.isSheetShowing()) {
bottomSheetLayout.dismissSheet();
} else {
bottomSheetLayout.showWithSheetView(bottomSheet);
}
}
底部购物车清单列表和右边商品列表的联动 (重点)
这篇博客,我们重点,说这里!说到这里,我们得先说明一下,购物车中商品的保存问题。说到保存,其实方案无非是两种:
1:加入购物车的商品保存在后台
保存在后台,每次的商品添加和减少,我们都要调取接口,这样对于app端来说,确实省了不少事,处理起来也方便不少。不太好的地方,就是调接口太频繁。如果后台开发人员比较牛,这种问题应该都是小问题。项目源码 中还没有对这种情况做展示处理。不过思路都差不多。
2: 加入购物车的商品保存在app本地
保存在app本地,也是一种不错的方案。项目源码 中,用的数据库框架是 GreenDao3.2,性能比较高。当然郭神的LitePal也很好啦!现在都更新到了3.0!
首先是商品的添加和减少,我们都要实时做本地数据库的更新处理。关键代码:
mContentAdapter.setOnAnimShopClickListener(new ContentAdapter.OnAnimShopClickListener() {
@Override
public void onAddSuccess(View view, int count, int position) {
ContentResult itemData = mContentAdapter.getItem(position);
saveData(count, itemData);
updateContentAdapter(itemData.getCount(), itemData.getProduct_id());
startAnimation(view, imageCart);
}
@Override
public void onDelSuccess(View view, int count, int position) {
ContentResult itemData = mContentAdapter.getItem(position);
saveData(count, itemData);
updateContentAdapter(itemData.getCount(), itemData.getProduct_id());
totalPriceCalculation();
}
});
每次点击底部购物车时,我们要根据当前用户,查出已经加入购物车的商品,关键代码如下:
frameShopCart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (tvNumber.getVisibility() == View.VISIBLE) {
List<ShopCartBean> shopCartBeans = shopCartBeanDao.queryBuilder()
.where(ShopCartBeanDao.Properties.User_id
.eq(mPreferencesUtil.getUserId()))
.build().list();
showPopupWindow(shopCartBeans);
}
}
});
下面关键问题来了,我们如何做到 底部购物车清单列表和右边商品列表的联动呢?
首先,当物车清单列表中的商品做增加或减少处理时,我们先要更新本地数据数据;
然后, 去 遍历 右边 列表,发现相同商品id的商品,它们的个数都要更新,然后刷新列表即可。
关键代码:
/**
* 刷新内容adapter
*/
private void updateContentAdapter(int count, String productId) {
// TODO: 2019/1/12 0012 这里后续优化,可以这样优化,相同商品的个数超过2个的再去刷新列表,否则就不要刷新列表啦
//去遍历列表,发现商品id相同的,个数 都赋值一样的。
for (ContentResult result : mContentResultList) {
if (productId.equals(result.getProduct_id())) {
result.setCount(count);
}
}
if (count == 0) {
//这样能保证动画效果能执行完毕,否则动画效果就会没有了。当然也可不做这样的处理,直接去刷新列表即可。
new Handler().postDelayed(() -> mContentAdapter.notifyDataSetChanged(), 400);
} else {
mContentAdapter.notifyDataSetChanged();
}
}
一些细节处理和注意事项
(1)商品加入购物车时,本地保存时要区分是哪个用户的。
(2)购物车商品减少时,减到0时的处理。
(3)一般商品类别中第一项会是 打折,促销 等类别,这个类别的商品id会和其他类别的商品id相同。要考虑到这种情况下的处理。
最后,文章从整理到写好,也花费了不少时间,如果对你有些帮助的话,给点个赞吧,谢谢啦!