feat(cart): 優化購物車品項數量調整邏輯與介面顯示
- 新增單一品項與總數量的調整限制邏輯,達上限時按鈕切換為 disabled 狀態 - 移除數量調整按鈕的陰影跳動與裁切問題 - 新增增加、減少、刪除按鈕的水波紋點擊反饋 - 在品項金額後方新增「庫存xx件」資訊,並統一樣式 - 購物車達數量上限時,顯示「已達數量上限」警告文字
This commit is contained in:
parent
e331e399bc
commit
0a19e965a8
@ -1,6 +1,8 @@
|
||||
package com.unibuy.v2.adapter
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.widget.ImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.chad.library.adapter.base.viewholder.BaseViewHolder
|
||||
import com.unibuy.smartdevice.R
|
||||
@ -12,6 +14,11 @@ import com.unibuy.v2.UnibuyHelper
|
||||
/**
|
||||
* 購物車品項清單 Adapter(自 Luzui v2 移植)。
|
||||
* 依賴 BaseRecyclerViewAdapterHelper 的 BaseQuickAdapter。
|
||||
*
|
||||
* Disabled 按鈕規則:
|
||||
* - buttonMinus:當 cartSelectedCount == 1 時 disabled(最低 1 件,不允許繼續減少)
|
||||
* - buttonPlus :當 cartSelectedCount >= slot.count(庫存上限)或全車總件數 >= 8 時 disabled
|
||||
* Disabled 外觀:背景換 bg_quantity_button_disabled、圖示染灰(#ADADAD)、clickable = false。
|
||||
*/
|
||||
class CartOperationAdapter(layoutResId: Int, data: MutableList<SlotStructure>) :
|
||||
BaseQuickAdapter<SlotStructure, BaseViewHolder>(layoutResId, data) {
|
||||
@ -22,8 +29,9 @@ class CartOperationAdapter(layoutResId: Int, data: MutableList<SlotStructure>) :
|
||||
|
||||
override fun convert(holder: BaseViewHolder, item: SlotStructure) {
|
||||
val result = UnibuyHelper.getCartViewModel().createResult(item)
|
||||
val ctx = holder.itemView.context
|
||||
|
||||
// 多國語商品名稱
|
||||
// ── 多國語商品名稱 ──────────────────────────────────────────────
|
||||
val lang = java.util.Locale.getDefault().language // "zh" / "en" / "ja"
|
||||
val name = when {
|
||||
lang.equals("en", ignoreCase = true) ->
|
||||
@ -43,13 +51,58 @@ class CartOperationAdapter(layoutResId: Int, data: MutableList<SlotStructure>) :
|
||||
|
||||
holder.setText(R.id.textProductName, name)
|
||||
.setText(R.id.totalPriceTextView, "NT$ ${result.currentItemPrice}")
|
||||
.setText(R.id.textStock, String.format("庫存%02d件", item.count))
|
||||
.setText(R.id.textQuantity, "${result.currentItemCount}")
|
||||
.setText(R.id.textPrice, "NT$ ${item.product.realPrice}")
|
||||
|
||||
// ── 商品圖片 ────────────────────────────────────────────────────
|
||||
val imageProductPicture = holder.getView<ImageView>(R.id.image_product)
|
||||
try {
|
||||
ImageGlide(imageProductPicture.context).fileload(item.product.productImg, imageProductPicture)
|
||||
} catch (e: LogsEmptyException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
// ── 按鈕 Disabled 狀態判斷 ──────────────────────────────────────
|
||||
val buttonMinus = holder.getView<ImageView>(R.id.buttonMinus)
|
||||
val buttonPlus = holder.getView<ImageView>(R.id.buttonPlus)
|
||||
|
||||
val isAtMinCount = item.cartSelectedCount <= 1
|
||||
val isAtStockLimit = item.cartSelectedCount >= item.count
|
||||
val isCartFull = UnibuyHelper.getCartViewModel().hasMinimumCartItems()
|
||||
val isPlusDisabled = isAtStockLimit || isCartFull
|
||||
|
||||
// ── 減少按鈕 ────────────────────────────────────────────────────
|
||||
applyButtonState(buttonMinus, disabled = isAtMinCount, ctx)
|
||||
|
||||
// ── 增加按鈕 ────────────────────────────────────────────────────
|
||||
applyButtonState(buttonPlus, disabled = isPlusDisabled, ctx)
|
||||
}
|
||||
|
||||
/**
|
||||
* 套用啟用 / 停用外觀到 ImageView 按鈕。
|
||||
*
|
||||
* @param button 目標按鈕
|
||||
* @param disabled true = 停用(light_gray 背景 + 灰色圖示 + 不可點擊)
|
||||
* @param ctx Context(取色用)
|
||||
*/
|
||||
private fun applyButtonState(button: ImageView, disabled: Boolean, ctx: android.content.Context) {
|
||||
if (disabled) {
|
||||
button.setBackgroundResource(R.drawable.bg_quantity_button_disabled)
|
||||
// setBackgroundResource 會重置 stateListAnimator,需立刻清除以防止陰影跳動
|
||||
button.stateListAnimator = null
|
||||
button.setColorFilter(
|
||||
ContextCompat.getColor(ctx, R.color.gray),
|
||||
PorterDuff.Mode.SRC_IN
|
||||
)
|
||||
button.isClickable = false
|
||||
} else {
|
||||
button.setBackgroundResource(R.drawable.bg_quantity_outline_button)
|
||||
// setBackgroundResource 會重置 stateListAnimator,需立刻清除以防止陰影跳動
|
||||
button.stateListAnimator = null
|
||||
button.clearColorFilter()
|
||||
button.isClickable = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -196,6 +196,12 @@ public class ShoppingCartFragment extends FragmentAbstract {
|
||||
allCartItems = UnibuyHelper.INSTANCE.getCartViewModel().getAllCartItems();
|
||||
binding.totalItemsTextView.setText(getString(R.string.total_items_format, allCartItems.getTotalCount()));
|
||||
binding.totalAmountTextView.setText(getString(R.string.total_amount_format, allCartItems.getTotalPrice()));
|
||||
|
||||
if (UnibuyHelper.INSTANCE.getCartViewModel().hasMinimumCartItems()) {
|
||||
binding.maxItemsWarningTextView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.maxItemsWarningTextView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/** 清空購物車並切回 VMC 商品列表。 */
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<!-- 停用狀態背景:light_gray -->
|
||||
<solid android:color="@color/light_gray" />
|
||||
<!-- 與啟用按鈕同款圓角 -->
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
@ -1,12 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<!-- 頁面背景色 -->
|
||||
<solid android:color="@color/background" />
|
||||
<!-- 黑色外框線 -->
|
||||
<stroke
|
||||
android:width="1.5dp"
|
||||
android:color="@color/black" />
|
||||
<!-- 圓角 -->
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/light_gray">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<!-- 頁面背景色 -->
|
||||
<solid android:color="@color/background" />
|
||||
<!-- 黑色外框線 -->
|
||||
<stroke
|
||||
android:width="1.5dp"
|
||||
android:color="@color/black" />
|
||||
<!-- 圓角 -->
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<!-- 頁面背景色 -->
|
||||
<solid android:color="@color/background" />
|
||||
<!-- 警告色外框線 -->
|
||||
<stroke
|
||||
android:width="1.5dp"
|
||||
android:color="@color/warning" />
|
||||
<!-- 圓角 -->
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/light_gray">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<!-- 頁面背景色 -->
|
||||
<solid android:color="@color/background" />
|
||||
<!-- 警告色外框線 -->
|
||||
<stroke
|
||||
android:width="1.5dp"
|
||||
android:color="@color/warning" />
|
||||
<!-- 圓角 -->
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
|
||||
@ -8,16 +8,35 @@
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- 購物車上方商品數量 -->
|
||||
<TextView
|
||||
android:id="@+id/totalItemsTextView"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingVertical="16dp"
|
||||
android:text="@string/total_items_format"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="23sp"
|
||||
android:textStyle="bold" />
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/totalItemsTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/total_items_format"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="23sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/maxItemsWarningTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="@string/cart_max_items_warning"
|
||||
android:textColor="@color/warning"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 购物车商品列表 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
@ -50,17 +50,35 @@
|
||||
android:text="$ 0"
|
||||
style="@style/TextAppearance.App.QuickCart.Small" />
|
||||
|
||||
<!-- 小記金額(移至此處) -->
|
||||
<TextView
|
||||
android:id="@+id/totalPriceTextView"
|
||||
<!-- 庫存與小記金額 -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="$ 0.0000"
|
||||
style="@style/TextAppearance.App.QuickCart.Medium"
|
||||
android:textColor="@color/primary" />
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/totalPriceTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="$ 0.0000"
|
||||
style="@style/TextAppearance.App.QuickCart.Medium"
|
||||
android:textColor="@color/primary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="庫存00件"
|
||||
android:layout_marginStart="16dp"
|
||||
style="@style/TextAppearance.App.QuickCart.Medium"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="normal" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -69,34 +87,50 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/buttonMinus"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/bg_quantity_outline_button"
|
||||
android:elevation="4dp"
|
||||
android:src="@drawable/remove_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textQuantity"
|
||||
android:layout_width="86dp"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="1"
|
||||
style="@style/TextAppearance.App.QuickCart.Medium"
|
||||
android:textColor="@color/black" />
|
||||
android:gravity="center_vertical"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/buttonMinus"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_margin="6dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/bg_quantity_outline_button"
|
||||
android:elevation="4dp"
|
||||
android:stateListAnimator="@null"
|
||||
android:src="@drawable/remove_24" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textQuantity"
|
||||
android:layout_width="86dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="1"
|
||||
style="@style/TextAppearance.App.QuickCart.Medium"
|
||||
android:textColor="@color/black" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/buttonPlus"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_margin="6dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/bg_quantity_outline_button"
|
||||
android:elevation="4dp"
|
||||
android:stateListAnimator="@null"
|
||||
android:src="@drawable/add_24" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/buttonPlus"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/bg_quantity_outline_button"
|
||||
android:elevation="4dp"
|
||||
android:src="@drawable/add_24" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 4. 刪除鈕(現有 Adapter / ShoppingCartFragment 沿用) -->
|
||||
@ -105,9 +139,13 @@
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/bg_waste_outline_button"
|
||||
android:elevation="4dp"
|
||||
android:stateListAnimator="@null"
|
||||
android:src="@drawable/close_warning_24" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@ -336,6 +336,8 @@
|
||||
<string name="cart_cannot_decrease">不能減少了</string>
|
||||
<string name="cart_max_items">購物車最多可購買 8 件商品</string>
|
||||
<string name="cart_added">已加入購物車</string>
|
||||
<string name="cart_max_items_warning">已達數量上限</string>
|
||||
|
||||
<string name="data_error">數據異常</string>
|
||||
<string name="product_delivery_success">商品出貨成功</string>
|
||||
<string name="please_go_to_cabinet_to_pick_up_goods">請至99號櫃門拿取您的商品</string>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user