refactor(adapter): 合并 Scale18/22GridAdapter 为 Seasoning18/22GridAdapter,统一支持调料配置和秤总览双模式
- ScaleData 新增可空 name 字段,用于承载调料名称 - Seasoning18/22GridAdapter 改用 ScaleData,新增 showNameOnly 参数区分页面模式 - showNameOnly=true(调料配置):仅显示名称,无名称显示"-" - showNameOnly=false(秤总览):显示名称+重量+状态,无名称显示秤地址编号 - update() 恢复差量更新逻辑,避免 submitList 动画期间点击失效 - MasterScaleActivity、SlaveActivity 改用新 Adapter,删除旧 Scale18/22GridAdapter - 删除 Scale22GridActivity 及其布局和 Manifest 注册 - list_item_scale22_row.xml 中 tvAddr 重命名为 tvName Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,8 +18,8 @@ import com.google.android.flexbox.FlexDirection
|
||||
import com.google.android.flexbox.FlexWrap
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.shuwei.dish.match.R
|
||||
import com.shuwei.dish.match.adapter.Scale18GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Scale22GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Seasoning18GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Seasoning22GridAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.dialog.CommonDialog
|
||||
import com.shuwei.dish.match.databinding.ActivityMasterScaleBinding
|
||||
@@ -249,7 +249,7 @@ class MasterScaleActivity : BaseActivity() {
|
||||
// ── ViewHolder: 22个秤 ─────────────────────────────────────────────────
|
||||
|
||||
private inner class Scale22VH(val b: ListTypeScale22Binding) : RecyclerView.ViewHolder(b.root) {
|
||||
private var innerAdapter: Scale22GridAdapter? = null
|
||||
private var innerAdapter: Seasoning22GridAdapter? = null
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(group: DeviceGroup) {
|
||||
@@ -269,8 +269,8 @@ class MasterScaleActivity : BaseActivity() {
|
||||
alignItems = AlignItems.FLEX_START
|
||||
}
|
||||
b.rvScales.itemAnimator = null
|
||||
innerAdapter = Scale22GridAdapter(largeSize, smallSize).apply {
|
||||
onItemClick = { scale ->
|
||||
innerAdapter = Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = false).apply {
|
||||
onItemClick = { scale, _ ->
|
||||
showTareDialog(deviceId = scale.deviceId, ip = scale.ip, address = scale.address)
|
||||
}
|
||||
}
|
||||
@@ -288,7 +288,7 @@ class MasterScaleActivity : BaseActivity() {
|
||||
// ── ViewHolder: 18个秤 ─────────────────────────────────────────────────
|
||||
|
||||
private inner class Scale18VH(val b: ListTypeScale18Binding) : RecyclerView.ViewHolder(b.root) {
|
||||
private var innerAdapter: Scale18GridAdapter? = null
|
||||
private var innerAdapter: Seasoning18GridAdapter? = null
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(group: DeviceGroup) {
|
||||
@@ -303,8 +303,8 @@ class MasterScaleActivity : BaseActivity() {
|
||||
}
|
||||
b.rvScales.layoutManager = gridLayoutManager
|
||||
b.rvScales.itemAnimator = null
|
||||
innerAdapter = Scale18GridAdapter().apply {
|
||||
onItemClick = { scale ->
|
||||
innerAdapter = Seasoning18GridAdapter(showNameOnly = false).apply {
|
||||
onItemClick = { scale, _ ->
|
||||
showTareDialog(deviceId = scale.deviceId, ip = scale.ip, address = scale.address)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
package com.shuwei.dish.match.ui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.flexbox.AlignItems
|
||||
import com.google.android.flexbox.FlexDirection
|
||||
import com.google.android.flexbox.FlexWrap
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.databinding.ActivityScale22GridBinding
|
||||
import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
|
||||
import com.shuwei.dish.match.scale.ScaleData
|
||||
import com.shuwei.dish.match.scale.ScaleServiceManager
|
||||
import com.shuwei.dish.match.utils.WeightUtil
|
||||
import com.shuwei.dish.match.utils.ext.dp
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** 22格设备的 deviceId */
|
||||
private const val DEVICE_ID_22 = "a46fa55c-113c-3511-bb1f-41e5eff77c4b"
|
||||
|
||||
/**
|
||||
* 列优先顺序:大列1(20,22) → 大列2(19,21) → 小列1~6
|
||||
* FlexboxLayoutManager COLUMN 方向按列填充,顺序天然对应
|
||||
*/
|
||||
private val SCALE_ORDER_22 = listOf(20, 22, 19, 21, 6, 12, 18, 5, 11, 17, 4, 10, 16, 3, 9, 15, 2, 8, 14, 1, 7, 13)
|
||||
|
||||
/** 前4个 item(大列1+大列2,各2行)为大格子 */
|
||||
private fun isLargeCell(position: Int) = position < 4
|
||||
|
||||
/**
|
||||
* 22格秤混合网格布局页
|
||||
* FlexboxLayoutManager(COLUMN) 竖向排列:
|
||||
* - 大格子 flexBasisPercent=1.5/9,每列2个,自动换列
|
||||
* - 小格子 flexBasisPercent=1.0/9,每列3个,自动换列
|
||||
*/
|
||||
class Scale22GridActivity : BaseActivity() {
|
||||
|
||||
private lateinit var binding: ActivityScale22GridBinding
|
||||
private val scaleList = mutableListOf<ScaleData?>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityScale22GridBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
setHeaderBackground()
|
||||
|
||||
binding.ivBack.setOnClickListener { finish() }
|
||||
|
||||
// 格子尺寸计算:
|
||||
// 屏幕宽 - 8列×左右margin(2dp×2) = 可用宽,共9份(大1.5+小1.0×6)
|
||||
val screenWidth = resources.displayMetrics.widthPixels
|
||||
val usable = screenWidth - 8 * 4.dp - 4.dp // 减去8列格子margin + RecyclerView左右margin各2dp
|
||||
val smallSize = usable / 9
|
||||
val largeSize = (usable - smallSize * 6) / 2 // 剩余宽度平分给2列大格子
|
||||
// 高度以小格子3行为准(3行×格子高 + 3行×上下margin各2dp)
|
||||
val rvHeight = smallSize * 3 + 3 * 4.dp
|
||||
binding.rvScale22.layoutParams = binding.rvScale22.layoutParams.also {
|
||||
it.height = rvHeight
|
||||
}
|
||||
|
||||
binding.rvScale22.layoutManager = FlexboxLayoutManager(this).apply {
|
||||
flexDirection = FlexDirection.COLUMN
|
||||
flexWrap = FlexWrap.WRAP
|
||||
alignItems = AlignItems.FLEX_START
|
||||
}
|
||||
binding.rvScale22.itemAnimator = null
|
||||
binding.rvScale22.adapter = Scale22Adapter(scaleList, largeSize, smallSize)
|
||||
|
||||
observeScaleData()
|
||||
}
|
||||
|
||||
private fun observeScaleData() {
|
||||
val flow = ScaleServiceManager.allScales ?: return
|
||||
lifecycleScope.launch {
|
||||
flow.collectLatest { scaleMap ->
|
||||
val scaleByAddress = scaleMap.values
|
||||
.filter { it.deviceId == DEVICE_ID_22 }
|
||||
.associateBy { it.address }
|
||||
val newList = SCALE_ORDER_22.map { scaleByAddress[it] }
|
||||
if (scaleList.isEmpty()) {
|
||||
scaleList.addAll(newList)
|
||||
binding.rvScale22.adapter?.notifyItemRangeInserted(0, scaleList.size)
|
||||
} else {
|
||||
newList.forEachIndexed { i, scale ->
|
||||
if (scaleList[i] != scale) {
|
||||
scaleList[i] = scale
|
||||
binding.rvScale22.adapter?.notifyItemChanged(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class Scale22Adapter(
|
||||
private val data: List<ScaleData?>,
|
||||
private val largeSize: Int, // 大格子宽高(px)
|
||||
private val smallSize: Int // 小格子宽高(px)
|
||||
) : RecyclerView.Adapter<Scale22Adapter.VH>() {
|
||||
|
||||
inner class VH(val b: ListItemScale22RowBinding) : RecyclerView.ViewHolder(b.root)
|
||||
|
||||
override fun getItemViewType(position: Int) = if (isLargeCell(position)) 1 else 0
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
|
||||
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
val cellSize = if (viewType == 1) largeSize else smallSize
|
||||
// 固定宽高实现正方形,FlexboxLayoutManager COLUMN 方向按高度装满后自动换列
|
||||
(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.tvAddr.textSize = (baseSp * 0.16f).coerceIn(9f, 14f)
|
||||
b.tvWeight.textSize = (baseSp * 0.22f).coerceIn(12f, 20f)
|
||||
b.tvState.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
|
||||
return VH(b)
|
||||
}
|
||||
|
||||
override fun getItemCount() = data.size
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
||||
val scale = data[position]
|
||||
holder.b.tvAddr.text = scale?.let { "秤${it.address}" } ?: ""
|
||||
holder.b.tvWeight.text = scale?.let { "${it.weight}g" } ?: ""
|
||||
holder.b.tvState.text = when (scale?.state) {
|
||||
WeightUtil.STATE_STABLE -> "稳定"
|
||||
WeightUtil.STATE_UNSTABLE -> "不稳定"
|
||||
WeightUtil.STATE_OVER_WEIGHT -> "超量"
|
||||
null -> ""
|
||||
else -> "${scale.state}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ import com.google.android.flexbox.AlignItems
|
||||
import com.google.android.flexbox.FlexDirection
|
||||
import com.google.android.flexbox.FlexWrap
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.shuwei.dish.match.adapter.Scale18GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Scale22GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Seasoning18GridAdapter
|
||||
import com.shuwei.dish.match.adapter.Seasoning22GridAdapter
|
||||
import com.shuwei.dish.match.adapter.ScaleRowAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.base.GlobalData
|
||||
@@ -40,9 +40,9 @@ class SlaveActivity : BaseActivity() {
|
||||
private val linearAdapter = ScaleRowAdapter()
|
||||
|
||||
/** 22个秤网格 adapter */
|
||||
private var scale22Adapter: Scale22GridAdapter? = null
|
||||
private var scale22Adapter: Seasoning22GridAdapter? = null
|
||||
/** 18个秤网格 adapter */
|
||||
private var scale18Adapter: Scale18GridAdapter? = null
|
||||
private var scale18Adapter: Seasoning18GridAdapter? = null
|
||||
|
||||
/** 已连接的主设备数量(有连接即代表主设备在线) */
|
||||
private var masterConnected = false
|
||||
@@ -95,8 +95,8 @@ class SlaveActivity : BaseActivity() {
|
||||
flexWrap = FlexWrap.WRAP
|
||||
alignItems = AlignItems.FLEX_START
|
||||
}
|
||||
scale22Adapter = Scale22GridAdapter(largeSize, smallSize).also {
|
||||
it.onItemClick = { scale -> showTareDialog(scale.address) }
|
||||
scale22Adapter = Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = false).also {
|
||||
it.onItemClick = { scale, _ -> showTareDialog(scale.address) }
|
||||
}
|
||||
binding.rvScaleList.adapter = scale22Adapter
|
||||
}
|
||||
@@ -107,8 +107,8 @@ class SlaveActivity : BaseActivity() {
|
||||
override fun getSpanSize(position: Int) = 1
|
||||
}
|
||||
}
|
||||
scale18Adapter = Scale18GridAdapter().also {
|
||||
it.onItemClick = { scale -> showTareDialog(scale.address) }
|
||||
scale18Adapter = Seasoning18GridAdapter(showNameOnly = false).also {
|
||||
it.onItemClick = { scale, _ -> showTareDialog(scale.address) }
|
||||
}
|
||||
binding.rvScaleList.adapter = scale18Adapter
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
||||
// private lateinit var appViewModel: AppViewModel
|
||||
|
||||
private val adapter22 by lazy { buildAdapter22() }
|
||||
private val adapter18 by lazy { Seasoning18GridAdapter() }
|
||||
private val adapter18 by lazy { Seasoning18GridAdapter(showNameOnly = true) }
|
||||
|
||||
/** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */
|
||||
private val weightSnapshot = mutableMapOf<String, Double>()
|
||||
@@ -96,7 +96,7 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
||||
val usable = resources.displayMetrics.widthPixels - 8 * 4.dp - 10.dp
|
||||
val smallSize = usable / 9
|
||||
val largeSize = (usable - smallSize * 6) / 2
|
||||
return Seasoning22GridAdapter(largeSize, smallSize)
|
||||
return Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = true)
|
||||
}
|
||||
|
||||
/** 配置两个 RecyclerView */
|
||||
|
||||
Reference in New Issue
Block a user