From c61b1c8ef7c5668acb003eea9b0bbc0d536962b3 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 17 Apr 2026 14:23:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(seasoning):=20=E6=B7=BB=E5=8A=A0=E8=B0=83?= =?UTF-8?q?=E6=96=99=E9=85=8D=E7=BD=AE=E7=BD=91=E6=A0=BC=E9=80=82=E9=85=8D?= =?UTF-8?q?=E5=99=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建调料配置格子布局文件,仅显示调料名称 - 实现调料配置下层18格网格适配器,使用GridLayoutManager排列 - 实现调料配置上层22格网格适配器,使用FlexboxLayoutManager排列 - 添加不同行列的边距控制和字体大小自适应 - 实现按预设顺序更新数据的功能,空位用哨兵填充 - 预留点击回调接口,暂不处理点击事件 --- .../match/adapter/Seasoning18GridAdapter.kt | 72 ++++++++++++++++++ .../match/adapter/Seasoning22GridAdapter.kt | 75 +++++++++++++++++++ .../res/layout/list_item_seasoning_cell.xml | 11 +++ 3 files changed, 158 insertions(+) create mode 100644 app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt create mode 100644 app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt create mode 100644 app/src/main/res/layout/list_item_seasoning_cell.xml diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt new file mode 100644 index 0000000..6d4201b --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt @@ -0,0 +1,72 @@ +package com.shuwei.dish.match.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter4.BaseQuickAdapter +import com.chad.library.adapter4.viewholder.QuickViewHolder +import com.shuwei.dish.match.databinding.ListItemSeasoningCellBinding +import com.shuwei.dish.match.entity.SeasoningEntity +import com.shuwei.dish.match.scale.ScaleDeviceConfig +import com.shuwei.dish.match.utils.ext.dp + +/** + * 调料配置-下层(18格)网格 Adapter + * 使用 GridLayoutManager(6列)排列,第1行格子 margin 较大,第2-3行 margin 较小 + * 实体类为 SeasoningEntity,格子显示调料名称 goodsName + */ +class Seasoning18GridAdapter : BaseQuickAdapter(mutableListOf()) { + + /** 空位哨兵,sort=-1 表示无效 */ + private val empty = SeasoningEntity(goodsId = "").also { it.sort = -1 } + + /** 点击回调,预留,暂不使用 */ + var onItemClick: ((SeasoningEntity, Int) -> Unit)? = null + + inner class VH(val b: ListItemSeasoningCellBinding) : QuickViewHolder(b.root) + + /** 前6个位置为第1行(viewType=0,margin大),其余为第2-3行(viewType=1,margin小) */ + override fun getItemViewType(position: Int, list: List) = + if (position < 6) 0 else 1 + + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val b = ListItemSeasoningCellBinding.inflate(LayoutInflater.from(context), parent, false) + val margin = if (viewType == 0) 12.dp else 2.dp + val screenWidth = parent.resources.displayMetrics.widthPixels + val cellSize = (screenWidth - 6 * margin * 2 - 10.dp) / 6 + (b.root.layoutParams as? ViewGroup.MarginLayoutParams)?.also { + it.width = cellSize + it.height = cellSize + // 第1行:顶部间距为0,底部间距2dp,左右保持原有 margin + if (viewType == 0) it.setMargins(margin, 0, margin, 2.dp) + else it.setMargins(margin, margin, margin, margin) + } + val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt() + b.tvGoodsName.textSize = (baseSp * 0.18f).coerceIn(10f, 16f) + val vh = VH(b) + // 点击事件预留,暂不处理 + b.root.setOnClickListener { + val pos = vh.bindingAdapterPosition + if (pos != RecyclerView.NO_POSITION) { + items.getOrNull(pos)?.let { item -> onItemClick?.invoke(item, pos) } + } + } + return vh + } + + override fun onBindViewHolder(holder: VH, position: Int, item: SeasoningEntity?) { + holder.b.tvGoodsName.text = item?.goodsName?.takeIf { it.isNotBlank() } ?: "-" + } + + /** + * 按 SCALE_ORDER_18 的 sort 顺序更新数据,空位用哨兵填充 + */ + fun update(seasoningList: List) { + val bySort = seasoningList.associateBy { it.sort } + val filled = ScaleDeviceConfig.SCALE_ORDER_18.map { sort -> + bySort[sort] ?: empty.copy().also { it.sort = sort } + } + submitList(filled) + } +} diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt new file mode 100644 index 0000000..59037e7 --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt @@ -0,0 +1,75 @@ +package com.shuwei.dish.match.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter4.BaseQuickAdapter +import com.chad.library.adapter4.viewholder.QuickViewHolder +import com.google.android.flexbox.FlexboxLayoutManager +import com.shuwei.dish.match.databinding.ListItemSeasoningCellBinding +import com.shuwei.dish.match.entity.SeasoningEntity +import com.shuwei.dish.match.scale.ScaleDeviceConfig +import com.shuwei.dish.match.utils.ext.dp + +/** + * 调料配置-上层(22格)网格 Adapter + * 使用 FlexboxLayoutManager 按列排列,前4个格子较大,其余较小 + * 实体类为 SeasoningEntity,格子显示调料名称 goodsName + * + * @param largeSize 前4个大格子的尺寸(px) + * @param smallSize 其余小格子的尺寸(px) + */ +class Seasoning22GridAdapter( + private val largeSize: Int, + private val smallSize: Int +) : BaseQuickAdapter(mutableListOf()) { + + /** 空位哨兵,sort=-1 表示无效 */ + private val empty = SeasoningEntity(goodsId = "").also { it.sort = -1 } + + /** 点击回调,预留,暂不使用 */ + var onItemClick: ((SeasoningEntity, Int) -> Unit)? = null + + inner class VH(val b: ListItemSeasoningCellBinding) : QuickViewHolder(b.root) + + /** 前4个位置为大格子(viewType=1),其余为小格子(viewType=0) */ + override fun getItemViewType(position: Int, list: List) = + if (position < 4) 1 else 0 + + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val b = ListItemSeasoningCellBinding.inflate(LayoutInflater.from(context), parent, false) + val cellSize = if (viewType == 1) largeSize else smallSize + (b.root.layoutParams as? FlexboxLayoutManager.LayoutParams)?.apply { + width = cellSize + height = cellSize + setMargins(2.dp, 2.dp, 2.dp, 2.dp) + } + val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt() + b.tvGoodsName.textSize = (baseSp * 0.18f).coerceIn(10f, 16f) + val vh = VH(b) + // 点击事件预留,暂不处理 + b.root.setOnClickListener { + val pos = vh.bindingAdapterPosition + if (pos != RecyclerView.NO_POSITION) { + items.getOrNull(pos)?.let { item -> onItemClick?.invoke(item, pos) } + } + } + return vh + } + + override fun onBindViewHolder(holder: VH, position: Int, item: SeasoningEntity?) { + holder.b.tvGoodsName.text = item?.goodsName?.takeIf { it.isNotBlank() } ?: "-" + } + + /** + * 按 SCALE_ORDER_22 的 sort 顺序更新数据,空位用哨兵填充 + */ + fun update(seasoningList: List) { + val bySort = seasoningList.associateBy { it.sort } + val filled = ScaleDeviceConfig.SCALE_ORDER_22.map { sort -> + bySort[sort] ?: empty.copy().also { it.sort = sort } + } + submitList(filled) + } +} diff --git a/app/src/main/res/layout/list_item_seasoning_cell.xml b/app/src/main/res/layout/list_item_seasoning_cell.xml new file mode 100644 index 0000000..a1883dc --- /dev/null +++ b/app/src/main/res/layout/list_item_seasoning_cell.xml @@ -0,0 +1,11 @@ + + +