购物车功能在电商项目中可以说是一个必不可少的功能了,但是在项目当中我们还是想将这个功能给尽可能的做的好看点、可观赏性强一点,所以我们便把目光投向了饿了么,毕竟那个动画还是挺好看的呢,这里先上布局文件看下效果
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_F4F4F4"
android:orientation="vertical">
<include layout="@layout/app_title_bar" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.3"
android:gravity="center"
android:text="我是商品分类"
android:textColor="@color/colorBlack"
android:textSize="12sp"
tools:ignore="HardcodedText,NestedWeights" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.7"
android:background="@color/colorWhite" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="55dp"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<TextView
android:id="@+id/tv_sum_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="70dp"
android:text="请添加商品"
android:textColor="@color/colorHint"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_settlement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="@drawable/btn_main_sure"
android:paddingStart="18dp"
android:paddingTop="9dp"
android:paddingEnd="18dp"
android:paddingBottom="9dp"
android:text="结算"
android:textColor="@color/colorWhite"
android:textSize="14sp" />
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/layout_cart"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_alignParentBottom="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_cart_left_bottom" />
<TextView
android:id="@+id/tv_cart_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_main_cart_number"
android:paddingStart="6dp"
android:paddingTop="2dp"
android:paddingEnd="6dp"
android:paddingBottom="2dp"
android:textColor="@color/colorWhite"
android:textSize="12sp"
android:visibility="gone"
tools:text="14"
tools:visibility="visible" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
接下来就是我们自定义的adapter
public class CartGoodsAdapter extends RecyclerView.Adapter {
private final List<CartGoodsBean> mData;
private int mAmountLeft;
private int mReduceLeft;
private int mAddLeft;
private final CartDetailUI cartActivity;
private final Context mContext;
public CartGoodsAdapter(Activity activity, Context mContext, List<CartGoodsBean> list) {
mData = list;
this.cartActivity = (CartDetailUI) activity;
this.mContext = mContext;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_cart_goods,
parent, false);
return new MyHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
final MyHolder myHolder = (MyHolder) holder;
myHolder.setItem(position);
final CartGoodsBean goodsBean = mData.get(position);
myHolder.itemName.setText(goodsBean.getGoodsName());
myHolder.itemSku.setText(goodsBean.getSku());
myHolder.itemPrice.setText(StringUtils.formatDouble(goodsBean.getSellPrice(), true));
final long[] clickTime = {0};
//点击加号
myHolder.itemPlus.setOnClickListener(view -> {
//屏蔽快速点击加入购物车问题
if (System.currentTimeMillis() - clickTime[0] <= 1000) {
return;
}
clickTime[0] = System.currentTimeMillis();
if (goodsBean.getCount() >= goodsBean.getStoreNumber()) {
ToastUtils.showToast(mContext, "商品库存不足");
return;
}
//如果该商品数量为0就进行 该动画
if (goodsBean.getCount() == 0) {
myHolder.itemMinus.setVisibility(View.VISIBLE);
myHolder.itemCartNumber.setVisibility(View.VISIBLE);
AnimatorSet set = new AnimatorSet();
//减号
ObjectAnimator ta1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"translationX", mAddLeft - mReduceLeft, 0);
ObjectAnimator ra1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"rotation", 0, 360);
ObjectAnimator aa1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"alpha", 0, 1);
//数字
ObjectAnimator ta2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"translationX", mAddLeft - mAmountLeft, 0);
ObjectAnimator ra2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"rotation", 0, 360);
ObjectAnimator aa2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"alpha", 0, 1);
set.play(ta1).with(ra1).with(ta2).with(ra2).with(aa1).with(aa2);
set.setDuration(500).start();
}
//得到加号在屏幕的坐标
int[] addLocation = new int[2];
view.getLocationInWindow(addLocation);
//得到购物车图标的坐标
int[] cartLocation = cartActivity.getCartLocation();
//添加一个imageview
final ImageView iv = new ImageView(view.getContext());
iv.setBackgroundResource(R.drawable.icon_plus);
RelativeLayout.LayoutParams lp =
new RelativeLayout.LayoutParams(view.getWidth(), view.getHeight());
lp.leftMargin = addLocation[0];
lp.topMargin = addLocation[1] - view.getHeight();
cartActivity.getContainer().addView(iv, lp);
//横向移动
ObjectAnimator oaX = ObjectAnimator.ofFloat(iv, "translationX",
cartLocation[0] - addLocation[0] + view.getWidth() / 2);
//纵向
ObjectAnimator oaY = ObjectAnimator.ofFloat(iv,
"translationY", cartLocation[1] - addLocation[1]);
oaX.setInterpolator(new LinearInterpolator());
oaY.setInterpolator(new AccelerateInterpolator());
AnimatorSet set = new AnimatorSet();
set.play(oaX).with(oaY);
set.setDuration(500).start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@SuppressLint("NotifyDataSetChanged")
@Override
public void onAnimationEnd(Animator animation) {
//移除这个view
cartActivity.getContainer().removeView(iv);
//更新购物车
goodsBean.setCount(goodsBean.getCount() + 1);
if (cartActivity.cartList.size() > 0) {
for (int i = 0; i < cartActivity.cartList.size(); i++) {
if (cartActivity.cartList.get(i).getSkuId() == goodsBean.getSkuId()) {
cartActivity.cartList.get(i).setCount(goodsBean.getCount());
break;
} else if (i == cartActivity.cartList.size() - 1) {
cartActivity.cartList.add(goodsBean);
break;
}
}
} else {
cartActivity.cartList.add(goodsBean);
}
((MyHolder) holder).itemCartNumber.setText(String.valueOf(goodsBean.getCount()));
cartActivity.mCount++;
cartActivity.setCartNumber();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
});
//点击减号
myHolder.itemMinus.setOnClickListener(view -> {
final CartGoodsBean cartModel = mData.get(position);
//如果该商品数量为1就进行这个动画
if (cartModel.getCount() == 1) {
AnimatorSet set = new AnimatorSet();
//减号
ObjectAnimator ta1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"translationX", 0, mAddLeft - mReduceLeft);
ObjectAnimator ra1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"rotation", 0, 360);
ObjectAnimator aa1 = ObjectAnimator.ofFloat(myHolder.itemMinus,
"alpha", 1, 0);
//数字
ObjectAnimator ta2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"translationX", 0, mAddLeft - mAmountLeft);
ObjectAnimator ra2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"rotation", 0, 360);
ObjectAnimator aa2 = ObjectAnimator.ofFloat(myHolder.itemCartNumber,
"alpha", 1, 0);
set.play(ta1).with(ra1).with(ta2).with(ra2).with(aa1).with(aa2);
set.setDuration(500).start();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@SuppressLint("NotifyDataSetChanged")
@Override
public void onAnimationEnd(Animator animation) {
cartModel.setCount(cartModel.getCount() - 1);
myHolder.itemCartNumber.setText(String.valueOf(cartModel.getCount()));
if (cartModel.getCount() == 0) {
myHolder.itemCartNumber.setVisibility(View.INVISIBLE);
myHolder.itemMinus.setVisibility(View.INVISIBLE);
}
if (cartActivity.cartList.size() > 0) {
for (int i = 0; i < cartActivity.cartList.size(); i++) {
if (cartActivity.cartList.get(i).getSkuId() == goodsBean.getSkuId()) {
if (cartActivity.cartList.get(i).getCount() == 0) {
cartActivity.cartList.remove(cartModel);
}
}
}
}
cartActivity.mCount--;
cartActivity.setCartNumber();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
} else {
cartModel.setCount(cartModel.getCount() - 1);
if (cartActivity.cartList.size() > 0) {
for (int i = 0; i < cartActivity.cartList.size(); i++) {
if (cartActivity.cartList.get(i).getSkuId() == goodsBean.getSkuId()) {
cartActivity.cartList.get(i).setCount(cartModel.getCount());
}
}
}
myHolder.itemCartNumber.setText(String.valueOf(cartModel.getCount()));
cartActivity.mCount--;
cartActivity.setCartNumber();
}
});
}
@Override
public int getItemCount() {
return mData.size();
}
class MyHolder extends RecyclerView.ViewHolder {
ImageView itemImage;
TextView itemName, itemSku, itemPrice, itemCartNumber;
ImageButton itemMinus, itemPlus;
LinearLayout layoutAdd;
public MyHolder(View itemView) {
super(itemView);
itemImage = itemView.findViewById(R.id.item_image);
itemName = itemView.findViewById(R.id.item_name);
itemSku = itemView.findViewById(R.id.item_sku);
itemCartNumber = itemView.findViewById(R.id.item_cart_number);
layoutAdd = itemView.findViewById(R.id.layout_add);
itemMinus = itemView.findViewById(R.id.item_minus);
itemPrice = itemView.findViewById(R.id.item_price);
itemPlus = itemView.findViewById(R.id.item_plus);
itemPlus.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到加号的左边位置
mAddLeft = itemPlus.getLeft();
itemPlus.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
itemMinus.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到减号的左边位置
mReduceLeft = itemMinus.getLeft();
itemMinus.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
itemCartNumber.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//得到价格的左边位置
mAmountLeft = itemCartNumber.getLeft();
itemCartNumber.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
public void setItem(int position) {
CartGoodsBean cartModel = mData.get(position);
itemName.setText(cartModel.getGoodsName());
itemCartNumber.setText(String.valueOf(cartModel.getCount()));
if (cartModel.getCount() > 0) {//数目大于0就显示
itemMinus.setVisibility(View.VISIBLE);
itemCartNumber.setVisibility(View.VISIBLE);
} else {//数目小于0就隐藏
itemMinus.setVisibility(View.INVISIBLE);
itemCartNumber.setVisibility(View.INVISIBLE);
}
}
}
}
到这里其实已经差不多完成了整个流程了,接下来在activity中进行调用就可以获取到我们所想要的功能了
goodsList.add(new CartGoodsBean(1, "红豆奶茶", "饿了么专享", 15, 3));
goodsList.add(new CartGoodsBean(12, "杨枝甘露", "饿了么专享", 8, 1));
goodsList.add(new CartGoodsBean(666, "抹茶奶绿", "饿了么专享", 13.09, 7));
goodsList.add(new CartGoodsBean(101, "冰红茶", "饿了么专享", 7.5, 10));
//商品列表
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
cartGoodsAdapter = new CartGoodsAdapter(this, mContext, goodsList);
binding.recyclerView.setAdapter(cartGoodsAdapter);
}
最后我们需要做的是在点击购物车图标的时候弹出购物车列表,这里我们我们直接贴上代码
/**
* 展开购物车列表
*/
private void showCartDialog() {
/* 获取屏幕信息 */
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height;
if (cartList.size() > 4) {
height = displayMetrics.heightPixels / 2;
} else {
height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
ShopCartDialog dialog = new ShopCartDialog(this, mContext, R.style.cartDialog);
Window window = dialog.getWindow();
dialog.setCancelable(true);
dialog.show();
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = height;
params.gravity = Gravity.BOTTOM;
params.dimAmount = 0f;
window.setAttributes(params);
}