feat(seasoning): 添加调料配置网格适配器功能

- 创建调料配置格子布局文件,仅显示调料名称
- 实现调料配置下层18格网格适配器,使用GridLayoutManager排列
- 实现调料配置上层22格网格适配器,使用FlexboxLayoutManager排列
- 添加不同行列的边距控制和字体大小自适应
- 实现按预设顺序更新数据的功能,空位用哨兵填充
- 预留点击回调接口,暂不处理点击事件
This commit is contained in:
2026-04-17 14:23:57 +08:00
parent 77df4a4d82
commit c61b1c8ef7
3 changed files with 158 additions and 0 deletions
@@ -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
* 使用 GridLayoutManager6列)排列,第1行格子 margin 较大,第2-3行 margin 较小
* 实体类为 SeasoningEntity,格子显示调料名称 goodsName
*/
class Seasoning18GridAdapter : BaseQuickAdapter<SeasoningEntity, Seasoning18GridAdapter.VH>(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=0margin大),其余为第2-3行(viewType=1margin小) */
override fun getItemViewType(position: Int, list: List<SeasoningEntity>) =
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<SeasoningEntity>) {
val bySort = seasoningList.associateBy { it.sort }
val filled = ScaleDeviceConfig.SCALE_ORDER_18.map { sort ->
bySort[sort] ?: empty.copy().also { it.sort = sort }
}
submitList(filled)
}
}
@@ -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<SeasoningEntity, Seasoning22GridAdapter.VH>(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<SeasoningEntity>) =
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<SeasoningEntity>) {
val bySort = seasoningList.associateBy { it.sort }
val filled = ScaleDeviceConfig.SCALE_ORDER_22.map { sort ->
bySort[sort] ?: empty.copy().also { it.sort = sort }
}
submitList(filled)
}
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 调料配置格子:仅显示调料名称 -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tvGoodsName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:includeFontPadding="false"
android:padding="4dp"
android:background="@drawable/shape_scale_cell"
android:textColor="@color/home_title" />