diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 330cdcc..88408ac 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -106,11 +106,6 @@
android:theme="@style/Theme.DishMatch.NoSplash"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
-
(mutableListOf()) {
-
- inner class VH(val b: ListItemScale22RowBinding) : QuickViewHolder(b.root)
-
- /** 用 address=0 的哨兵表示空位 */
- private val empty = ScaleData("", 0, 0.0, -1, 0)
-
- /** 当前高亮的格子位置,-1 表示无高亮 */
- private var highlightedPosition: Int = -1
-
- /** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
- var onItemClick: ((ScaleData) -> Unit)? = null
-
- /**
- * 按 SCALE_ORDER_18 顺序更新数据,空位用哨兵填充
- * 只更新显示字段有变化的格子,避免全量刷新
- */
- fun update(newList: List) {
- val filled = newList.map { it ?: empty }
- if (items.isEmpty()) {
- submitList(filled)
- } else {
- filled.forEachIndexed { i, scale ->
- val cur = items.getOrNull(i)
- if (cur == null || cur.address != scale.address || cur.weight != scale.weight || cur.state != scale.state) {
- set(i, scale)
- }
- }
- }
- }
-
- /**
- * 将 ScaleData 列表按 SCALE_ORDER_18 重排后调用 update
- */
- fun updateByAddress(scales: List) {
- val byAddress = scales.associateBy { it.address }
- update(ScaleDeviceConfig.SCALE_ORDER_18.map { byAddress[it] })
- }
-
- /** 前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 = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
- // 第1行 margin=12dp(格子视觉更小),第2-3行 margin=2dp
- 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 = (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.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)
- val vh = VH(b)
- // 在 ViewHolder 创建时绑定点击,只执行一次,不受 notifyItemChanged 重绑定影响
- b.root.setOnClickListener {
- val pos = vh.bindingAdapterPosition
- if (pos != RecyclerView.NO_POSITION) {
- items.getOrNull(pos)?.takeIf { it.address != 0 }?.let { onItemClick?.invoke(it) }
- }
- }
- return vh
- }
-
- @SuppressLint("SetTextI18n")
- override fun onBindViewHolder(holder: VH, position: Int, item: ScaleData?) {
- val valid = (item?.address ?: 0) != 0
- holder.b.tvAddr.text = if (valid) "秤${item!!.address}" else ""
- holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
- holder.b.tvState.text = if (valid) stateStr(item!!.state) else ""
- // 高亮格子:红底白字;其余恢复默认
- if (position == highlightedPosition) {
- holder.b.root.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
- val white = ContextCompat.getColor(holder.b.root.context, R.color.white)
- holder.b.tvAddr.setTextColor(white)
- holder.b.tvWeight.setTextColor(white)
- holder.b.tvState.setTextColor(white)
- } else {
- holder.b.root.setBackgroundResource(R.drawable.shape_scale_cell)
- val normal = ContextCompat.getColor(holder.b.root.context, R.color.home_title)
- holder.b.tvAddr.setTextColor(normal)
- holder.b.tvWeight.setTextColor(normal)
- holder.b.tvState.setTextColor(normal)
- }
- }
-
- /**
- * 高亮指定位置的格子(红底白字),同时清除上一个高亮
- * @param position 要高亮的格子索引
- */
- fun highlightPosition(position: Int) {
- val prev = highlightedPosition
- highlightedPosition = position
- if (prev >= 0) notifyItemChanged(prev)
- if (position >= 0) notifyItemChanged(position)
- }
-
- /**
- * 清除所有高亮,恢复默认样式
- */
- fun clearHighlight() {
- highlightPosition(-1)
- }
-
- private fun stateStr(state: Int) = when (state) {
- WeightUtil.STATE_STABLE -> "稳定"
- WeightUtil.STATE_UNSTABLE -> "不稳定"
- WeightUtil.STATE_OVER_WEIGHT -> "超量"
- else -> "$state"
- }
-}
diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/Scale22GridAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/Scale22GridAdapter.kt
deleted file mode 100644
index 9b9e550..0000000
--- a/app/src/main/java/com/shuwei/dish/match/adapter/Scale22GridAdapter.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.shuwei.dish.match.adapter
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.core.content.ContextCompat
-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.R
-import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
-import com.shuwei.dish.match.scale.ScaleData
-import com.shuwei.dish.match.scale.ScaleDeviceConfig
-import com.shuwei.dish.match.utils.WeightUtil
-import com.shuwei.dish.match.utils.ext.dp
-
-/**
- * 22个秤的网格 Adapter
- * 使用 FlexboxLayoutManager 按列排列,前4个格子较大(对应物理上的大秤),其余较小
- * 点击格子触发清零回调
- *
- * @param largeSize 前4个大格子的尺寸(px)
- * @param smallSize 其余小格子的尺寸(px)
- */
-class Scale22GridAdapter(
- private val largeSize: Int,
- private val smallSize: Int
-) : BaseQuickAdapter(mutableListOf()) {
-
- inner class VH(val b: ListItemScale22RowBinding) : QuickViewHolder(b.root)
-
- /** 用 address=0 的哨兵表示空位 */
- private val empty = ScaleData("", 0, 0.0, -1, 0)
-
- /** 当前高亮的格子位置,-1 表示无高亮 */
- private var highlightedPosition: Int = -1
-
- /** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
- var onItemClick: ((ScaleData) -> Unit)? = null
-
- /**
- * 按 SCALE_ORDER_22 顺序更新数据,空位用哨兵填充
- * 只更新显示字段有变化的格子,避免全量刷新
- */
- fun update(newList: List) {
- val filled = newList.map { it ?: empty }
- if (items.isEmpty()) {
- submitList(filled)
- } else {
- filled.forEachIndexed { i, scale ->
- val cur = items.getOrNull(i)
- if (cur == null || cur.address != scale.address || cur.weight != scale.weight || cur.state != scale.state) {
- set(i, scale)
- }
- }
- }
- }
-
- /**
- * 将 ScaleData 列表按 SCALE_ORDER_22 重排后调用 update
- */
- fun updateByAddress(scales: List) {
- val byAddress = scales.associateBy { it.address }
- update(ScaleDeviceConfig.SCALE_ORDER_22.map { byAddress[it] })
- }
-
- /** 前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 = ListItemScale22RowBinding.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.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)
- val vh = VH(b)
- // 在 ViewHolder 创建时绑定点击,只执行一次,不受 notifyItemChanged 重绑定影响
- b.root.setOnClickListener {
- val pos = vh.bindingAdapterPosition
- if (pos != RecyclerView.NO_POSITION) {
- items.getOrNull(pos)?.takeIf { it.address != 0 }?.let { onItemClick?.invoke(it) }
- }
- }
- return vh
- }
-
- @SuppressLint("SetTextI18n")
- override fun onBindViewHolder(holder: VH, position: Int, item: ScaleData?) {
- val valid = (item?.address ?: 0) != 0
- holder.b.tvAddr.text = if (valid) "秤${item!!.address}" else ""
- holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
- holder.b.tvState.text = if (valid) stateStr(item!!.state) else ""
- // 高亮格子:红底白字;其余恢复默认
- if (position == highlightedPosition) {
- holder.b.root.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
- val white = ContextCompat.getColor(holder.b.root.context, R.color.white)
- holder.b.tvAddr.setTextColor(white)
- holder.b.tvWeight.setTextColor(white)
- holder.b.tvState.setTextColor(white)
- } else {
- holder.b.root.setBackgroundResource(R.drawable.shape_scale_cell)
- val normal = ContextCompat.getColor(holder.b.root.context, R.color.home_title)
- holder.b.tvAddr.setTextColor(normal)
- holder.b.tvWeight.setTextColor(normal)
- holder.b.tvState.setTextColor(normal)
- }
- }
-
- /**
- * 高亮指定位置的格子(红底白字),同时清除上一个高亮
- * @param position 要高亮的格子索引
- */
- fun highlightPosition(position: Int) {
- val prev = highlightedPosition
- highlightedPosition = position
- if (prev >= 0) notifyItemChanged(prev)
- if (position >= 0) notifyItemChanged(position)
- }
-
- /**
- * 清除所有高亮,恢复默认样式
- */
- fun clearHighlight() {
- highlightPosition(-1)
- }
-
- private fun stateStr(state: Int) = when (state) {
- WeightUtil.STATE_STABLE -> "稳定"
- WeightUtil.STATE_UNSTABLE -> "不稳定"
- WeightUtil.STATE_OVER_WEIGHT -> "超量"
- else -> "$state"
- }
-}
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
index f7d94cb..7512cc9 100644
--- a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt
+++ b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt
@@ -1,80 +1,110 @@
package com.shuwei.dish.match.adapter
+import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
+import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.R
-import com.shuwei.dish.match.databinding.ListItemSeasoningCellBinding
-import com.shuwei.dish.match.entity.SeasoningEntity
+import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
+import com.shuwei.dish.match.scale.ScaleData
import com.shuwei.dish.match.scale.ScaleDeviceConfig
+import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.dp
/**
- * 调料配置-下层(18格)网格 Adapter
- * 使用 GridLayoutManager(6列)排列,第1行格子 margin 较大,第2-3行 margin 较小
- * 实体类为 SeasoningEntity,格子显示调料名称 goodsName
+ * 18格网格 Adapter,同时服务于调料配置页和主设备秤总览页。
+ *
+ * @param showNameOnly true = 调料配置模式,仅显示 tvName,隐藏 tvWeight/tvState;
+ * false = 秤总览模式,三行全部显示
*/
-class Seasoning18GridAdapter : BaseQuickAdapter(mutableListOf()) {
+class Seasoning18GridAdapter(
+ private val showNameOnly: Boolean = false
+) : BaseQuickAdapter(mutableListOf()) {
- /** 空位哨兵,sort=-1 表示无效 */
- private val empty = SeasoningEntity(goodsId = "").also { it.sort = -1 }
+ /** 空位哨兵,address=0 表示无效 */
+ private val empty = ScaleData("", 0, 0.0, -1, 0)
/** 当前高亮的格子位置,-1 表示无高亮 */
private var highlightedPosition: Int = -1
- /** 点击回调,预留,暂不使用 */
- var onItemClick: ((SeasoningEntity, Int) -> Unit)? = null
+ /** 点击回调 */
+ var onItemClick: ((ScaleData, Int) -> Unit)? = null
- inner class VH(val b: ListItemSeasoningCellBinding) : QuickViewHolder(b.root)
+ inner class VH(val b: ListItemScale22RowBinding) : QuickViewHolder(b.root)
/** 前6个位置为第1行(viewType=0,margin大),其余为第2-3行(viewType=1,margin小) */
- override fun getItemViewType(position: Int, list: List) =
+ 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 b = ListItemScale22RowBinding.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)
+ b.tvName.textSize = (baseSp * 0.18f).coerceIn(10f, 16f)
+ b.tvWeight.textSize = (baseSp * 0.22f).coerceIn(12f, 20f)
+ b.tvState.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
+ // 调料配置模式隐藏重量和状态行
+ if (showNameOnly) {
+ b.tvWeight.visibility = View.GONE
+ b.tvState.visibility = View.GONE
+ }
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) }
+ items.getOrNull(pos)?.takeIf { it.address != 0 }?.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() } ?: "-"
+ @SuppressLint("SetTextI18n")
+ override fun onBindViewHolder(holder: VH, position: Int, item: ScaleData?) {
+ val valid = (item?.address ?: 0) != 0
+ if (!valid) {
+ holder.b.tvName.text = if (showNameOnly) "-" else ""
+ holder.b.tvWeight.text = ""
+ holder.b.tvState.text = ""
+ } else {
+ holder.b.tvName.text = when {
+ !item!!.name.isNullOrBlank() -> item.name
+ showNameOnly -> "-"
+ else -> "秤${item.address}"
+ }
+ holder.b.tvWeight.text = "${item!!.weight}g"
+ holder.b.tvState.text = stateStr(item.state)
+ }
// 高亮格子:红底白字;其余恢复默认
if (position == highlightedPosition) {
- holder.b.tvGoodsName.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
- holder.b.tvGoodsName.setTextColor(ContextCompat.getColor(holder.b.root.context, R.color.white))
+ holder.b.root.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
+ val white = ContextCompat.getColor(holder.b.root.context, R.color.white)
+ holder.b.tvName.setTextColor(white)
+ holder.b.tvWeight.setTextColor(white)
+ holder.b.tvState.setTextColor(white)
} else {
- holder.b.tvGoodsName.setBackgroundResource(R.drawable.shape_scale_cell)
- holder.b.tvGoodsName.setTextColor(ContextCompat.getColor(holder.b.root.context, R.color.home_title))
+ holder.b.root.setBackgroundResource(R.drawable.shape_scale_cell)
+ val normal = ContextCompat.getColor(holder.b.root.context, R.color.home_title)
+ holder.b.tvName.setTextColor(normal)
+ holder.b.tvWeight.setTextColor(normal)
+ holder.b.tvState.setTextColor(normal)
}
}
/**
* 高亮指定位置的格子(红底白字),同时清除上一个高亮
- * @param position 要高亮的格子索引
*/
fun highlightPosition(position: Int) {
val prev = highlightedPosition
@@ -91,23 +121,46 @@ class Seasoning18GridAdapter : BaseQuickAdapter) {
- val bySort = seasoningList.associateBy { it.sort }
- val filled = ScaleDeviceConfig.SCALE_ORDER_18.map { sort ->
- bySort[sort] ?: empty.copy().also { it.sort = sort }
+ fun update(list: List) {
+ val byAddress = list.associateBy { it.address }
+ val filled = ScaleDeviceConfig.SCALE_ORDER_18.map { addr ->
+ byAddress[addr] ?: empty.copy(address = addr)
}
- submitList(filled)
+ if (items.isEmpty()) {
+ submitList(filled)
+ } else {
+ filled.forEachIndexed { i, scale ->
+ val cur = items.getOrNull(i)
+ if (cur == null || cur.address != scale.address || cur.weight != scale.weight || cur.state != scale.state || cur.name != scale.name) {
+ set(i, scale)
+ }
+ }
+ }
+ }
+
+ /**
+ * 将 ScaleData 列表按 SCALE_ORDER_18 重排后调用 update
+ */
+ fun updateByAddress(scales: List) {
+ update(scales)
+ }
+
+ private fun stateStr(state: Int) = when (state) {
+ WeightUtil.STATE_STABLE -> "稳定"
+ WeightUtil.STATE_UNSTABLE -> "不稳定"
+ WeightUtil.STATE_OVER_WEIGHT -> "超量"
+ else -> ""
}
}
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
index a089296..51136b4 100644
--- a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt
+++ b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning22GridAdapter.kt
@@ -1,7 +1,9 @@
package com.shuwei.dish.match.adapter
+import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
+import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
@@ -9,41 +11,43 @@ import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.google.android.flexbox.FlexboxLayoutManager
import com.shuwei.dish.match.R
-import com.shuwei.dish.match.databinding.ListItemSeasoningCellBinding
-import com.shuwei.dish.match.entity.SeasoningEntity
+import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
+import com.shuwei.dish.match.scale.ScaleData
import com.shuwei.dish.match.scale.ScaleDeviceConfig
+import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.dp
/**
- * 调料配置-上层(22格)网格 Adapter
- * 使用 FlexboxLayoutManager 按列排列,前4个格子较大,其余较小
- * 实体类为 SeasoningEntity,格子显示调料名称 goodsName
+ * 22格网格 Adapter,同时服务于调料配置页和主设备秤总览页。
*
- * @param largeSize 前4个大格子的尺寸(px)
- * @param smallSize 其余小格子的尺寸(px)
+ * @param largeSize 前4个大格子的尺寸(px)
+ * @param smallSize 其余小格子的尺寸(px)
+ * @param showNameOnly true = 调料配置模式,仅显示 tvName,隐藏 tvWeight/tvState;
+ * false = 秤总览模式,三行全部显示
*/
class Seasoning22GridAdapter(
private val largeSize: Int,
- private val smallSize: Int
-) : BaseQuickAdapter(mutableListOf()) {
+ private val smallSize: Int,
+ private val showNameOnly: Boolean = false
+) : BaseQuickAdapter(mutableListOf()) {
- /** 空位哨兵,sort=-1 表示无效 */
- private val empty = SeasoningEntity(goodsId = "").also { it.sort = -1 }
+ /** 空位哨兵,address=0 表示无效 */
+ private val empty = ScaleData("", 0, 0.0, -1, 0)
/** 当前高亮的格子位置,-1 表示无高亮 */
private var highlightedPosition: Int = -1
- /** 点击回调,预留,暂不使用 */
- var onItemClick: ((SeasoningEntity, Int) -> Unit)? = null
+ /** 点击回调 */
+ var onItemClick: ((ScaleData, Int) -> Unit)? = null
- inner class VH(val b: ListItemSeasoningCellBinding) : QuickViewHolder(b.root)
+ inner class VH(val b: ListItemScale22RowBinding) : QuickViewHolder(b.root)
/** 前4个位置为大格子(viewType=1),其余为小格子(viewType=0) */
- override fun getItemViewType(position: Int, list: List) =
+ 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 b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
val cellSize = if (viewType == 1) largeSize else smallSize
(b.root.layoutParams as? FlexboxLayoutManager.LayoutParams)?.apply {
width = cellSize
@@ -51,33 +55,59 @@ class Seasoning22GridAdapter(
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)
+ b.tvName.textSize = (baseSp * 0.18f).coerceIn(10f, 16f)
+ b.tvWeight.textSize = (baseSp * 0.22f).coerceIn(12f, 20f)
+ b.tvState.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
+ // 调料配置模式隐藏重量和状态行
+ if (showNameOnly) {
+ b.tvWeight.visibility = View.GONE
+ b.tvState.visibility = View.GONE
+ }
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) }
+ items.getOrNull(pos)?.takeIf { it.address != 0 }?.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() } ?: "-"
+ @SuppressLint("SetTextI18n")
+ override fun onBindViewHolder(holder: VH, position: Int, item: ScaleData?) {
+ val valid = (item?.address ?: 0) != 0
+ if (!valid) {
+ holder.b.tvName.text = if (showNameOnly) "-" else ""
+ holder.b.tvWeight.text = ""
+ holder.b.tvState.text = ""
+ } else {
+ // 有名称显示名称,无名称:调料配置显示"-",秤总览显示秤地址编号
+ holder.b.tvName.text = when {
+ !item!!.name.isNullOrBlank() -> item.name
+ showNameOnly -> "-"
+ else -> "秤${item.address}"
+ }
+ holder.b.tvWeight.text = "${item!!.weight}g"
+ holder.b.tvState.text = stateStr(item.state)
+ }
// 高亮格子:红底白字;其余恢复默认
if (position == highlightedPosition) {
- holder.b.tvGoodsName.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
- holder.b.tvGoodsName.setTextColor(ContextCompat.getColor(holder.b.root.context, R.color.white))
+ holder.b.root.setBackgroundColor(ContextCompat.getColor(holder.b.root.context, R.color.red_ff4444))
+ val white = ContextCompat.getColor(holder.b.root.context, R.color.white)
+ holder.b.tvName.setTextColor(white)
+ holder.b.tvWeight.setTextColor(white)
+ holder.b.tvState.setTextColor(white)
} else {
- holder.b.tvGoodsName.setBackgroundResource(R.drawable.shape_scale_cell)
- holder.b.tvGoodsName.setTextColor(ContextCompat.getColor(holder.b.root.context, R.color.home_title))
+ holder.b.root.setBackgroundResource(R.drawable.shape_scale_cell)
+ val normal = ContextCompat.getColor(holder.b.root.context, R.color.home_title)
+ holder.b.tvName.setTextColor(normal)
+ holder.b.tvWeight.setTextColor(normal)
+ holder.b.tvState.setTextColor(normal)
}
}
/**
* 高亮指定位置的格子(红底白字),同时清除上一个高亮
- * @param position 要高亮的格子索引
*/
fun highlightPosition(position: Int) {
val prev = highlightedPosition
@@ -94,23 +124,46 @@ class Seasoning22GridAdapter(
}
/**
- * 更新指定位置的调料名称并刷新对应格子
- * @param position 格子索引
- * @param name 新的调料名称
+ * 更新指定位置的名称并刷新对应格子
*/
fun updateItemName(position: Int, name: String) {
- items.getOrNull(position)?.goodsName = name
- notifyItemChanged(position)
+ items.getOrNull(position)?.let {
+ set(position, it.copy(name = name))
+ }
}
/**
* 按 SCALE_ORDER_22 的 sort 顺序更新数据,空位用哨兵填充
+ * 只更新显示字段有变化的格子,避免全量刷新导致 ViewHolder 重建影响点击监听
*/
- 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 }
+ fun update(list: List) {
+ val byAddress = list.associateBy { it.address }
+ val filled = ScaleDeviceConfig.SCALE_ORDER_22.map { addr ->
+ byAddress[addr] ?: empty.copy(address = addr)
}
- submitList(filled)
+ if (items.isEmpty()) {
+ submitList(filled)
+ } else {
+ filled.forEachIndexed { i, scale ->
+ val cur = items.getOrNull(i)
+ if (cur == null || cur.address != scale.address || cur.weight != scale.weight || cur.state != scale.state || cur.name != scale.name) {
+ set(i, scale)
+ }
+ }
+ }
+ }
+
+ /**
+ * 将 ScaleData 列表按 SCALE_ORDER_22 重排后调用 update
+ */
+ fun updateByAddress(scales: List) {
+ update(scales)
+ }
+
+ private fun stateStr(state: Int) = when (state) {
+ WeightUtil.STATE_STABLE -> "稳定"
+ WeightUtil.STATE_UNSTABLE -> "不稳定"
+ WeightUtil.STATE_OVER_WEIGHT -> "超量"
+ else -> ""
}
}
diff --git a/app/src/main/java/com/shuwei/dish/match/scale/ScaleData.kt b/app/src/main/java/com/shuwei/dish/match/scale/ScaleData.kt
index 384441e..2fa647c 100644
--- a/app/src/main/java/com/shuwei/dish/match/scale/ScaleData.kt
+++ b/app/src/main/java/com/shuwei/dish/match/scale/ScaleData.kt
@@ -15,5 +15,6 @@ data class ScaleData(
val weight: Double,
val state: Int,
val ts: Long,
- val ip: String = ""
+ val ip: String = "",
+ val name: String? = null
)
diff --git a/app/src/main/java/com/shuwei/dish/match/ui/MasterScaleActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/MasterScaleActivity.kt
index 35213b1..b9af322 100644
--- a/app/src/main/java/com/shuwei/dish/match/ui/MasterScaleActivity.kt
+++ b/app/src/main/java/com/shuwei/dish/match/ui/MasterScaleActivity.kt
@@ -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)
}
}
diff --git a/app/src/main/java/com/shuwei/dish/match/ui/Scale22GridActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/Scale22GridActivity.kt
deleted file mode 100644
index 12e5778..0000000
--- a/app/src/main/java/com/shuwei/dish/match/ui/Scale22GridActivity.kt
+++ /dev/null
@@ -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()
-
- 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,
- private val largeSize: Int, // 大格子宽高(px)
- private val smallSize: Int // 小格子宽高(px)
- ) : RecyclerView.Adapter() {
-
- 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}"
- }
- }
- }
-}
diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SlaveActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SlaveActivity.kt
index 0013c09..8a58657 100644
--- a/app/src/main/java/com/shuwei/dish/match/ui/SlaveActivity.kt
+++ b/app/src/main/java/com/shuwei/dish/match/ui/SlaveActivity.kt
@@ -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
}
diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt
index f4f2700..cb94fc7 100644
--- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt
+++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt
@@ -45,7 +45,7 @@ class SeasoningConfigFragment : BaseFragment() {
// 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()
@@ -96,7 +96,7 @@ class SeasoningConfigFragment : BaseFragment() {
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 */
diff --git a/app/src/main/res/layout/activity_scale22_grid.xml b/app/src/main/res/layout/activity_scale22_grid.xml
deleted file mode 100644
index 79662cb..0000000
--- a/app/src/main/res/layout/activity_scale22_grid.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/list_item_scale22_row.xml b/app/src/main/res/layout/list_item_scale22_row.xml
index a66ac96..9376d52 100644
--- a/app/src/main/res/layout/list_item_scale22_row.xml
+++ b/app/src/main/res/layout/list_item_scale22_row.xml
@@ -9,7 +9,7 @@
android:background="@drawable/shape_scale_cell">