feat(activity): 为子设备 SlaveActivity 添加调料秤重量增加高亮提醒功能

检测本机秤稳定后重量增加超过10g,高亮对应格子(红底白字),15秒后自动恢复
This commit is contained in:
2026-04-20 09:08:44 +08:00
parent 87bf11454c
commit 193acff1e0
3 changed files with 112 additions and 1 deletions
@@ -1,12 +1,14 @@
package com.shuwei.dish.match.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import android.annotation.SuppressLint
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.ListItemScale22RowBinding
import com.shuwei.dish.match.scale.ScaleData
import com.shuwei.dish.match.scale.ScaleDeviceConfig
@@ -25,6 +27,9 @@ class Scale18GridAdapter : BaseQuickAdapter<ScaleData, Scale18GridAdapter.VH>(mu
/** 用 address=0 的哨兵表示空位 */
private val empty = ScaleData("", 0, 0.0, -1, 0)
/** 当前高亮的格子位置,-1 表示无高亮 */
private var highlightedPosition: Int = -1
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
var onItemClick: ((ScaleData) -> Unit)? = null
@@ -91,6 +96,38 @@ class Scale18GridAdapter : BaseQuickAdapter<ScaleData, Scale18GridAdapter.VH>(mu
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) {
@@ -4,10 +4,12 @@ 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
@@ -32,6 +34,9 @@ class Scale22GridAdapter(
/** 用 address=0 的哨兵表示空位 */
private val empty = ScaleData("", 0, 0.0, -1, 0)
/** 当前高亮的格子位置,-1 表示无高亮 */
private var highlightedPosition: Int = -1
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
var onItemClick: ((ScaleData) -> Unit)? = null
@@ -93,6 +98,38 @@ class Scale22GridAdapter(
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) {
@@ -2,6 +2,8 @@ package com.shuwei.dish.match.ui
import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
@@ -45,6 +47,13 @@ class SlaveActivity : BaseActivity() {
/** 已连接的主设备数量(有连接即代表主设备在线) */
private var masterConnected = false
/** 各秤地址的上一次重量快照,用于计算 delta */
private val weightSnapshot = mutableMapOf<Int, Double>()
/** 主线程 Handler,用于延迟清除高亮 */
private val mainHandler = Handler(Looper.getMainLooper())
/** 当前高亮清除任务,新高亮触发时取消旧任务 */
private var clearHighlightRunnable: Runnable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySlaveBinding.inflate(layoutInflater)
@@ -134,9 +143,19 @@ class SlaveActivity : BaseActivity() {
/**
* 监听本机 WeightUtil 回调,实时刷新秤列表
* 22/18个秤走网格 adapter,其余走线性列表
* 秤稳定且重量增加超过阈值时,高亮对应格子,15秒后自动恢复
*/
private fun listenLocalScales() {
WeightUtil.addWeightListener(TAG) { address, state, weight ->
// 重量快照与高亮判断(在回调线程计算,不涉及 UI)
val baseline = weightSnapshot[address]
val shouldHighlight = baseline != null
&& state == WeightUtil.STATE_STABLE
&& (weight - baseline) > WEIGHT_DELTA_THRESHOLD
if (baseline == null || state == WeightUtil.STATE_STABLE) {
weightSnapshot[address] = weight
}
runOnUiThread {
when {
scale22Adapter != null -> {
@@ -167,6 +186,19 @@ class SlaveActivity : BaseActivity() {
linearAdapter.submitList(list)
}
}
// 触发格子高亮
if (shouldHighlight) {
clearHighlightRunnable?.let { mainHandler.removeCallbacks(it) }
val pos22 = ScaleDeviceConfig.SCALE_ORDER_22.indexOf(address)
val pos18 = ScaleDeviceConfig.SCALE_ORDER_18.indexOf(address)
scale22Adapter?.highlightPosition(pos22)
scale18Adapter?.highlightPosition(pos18)
clearHighlightRunnable = Runnable {
scale22Adapter?.clearHighlight()
scale18Adapter?.clearHighlight()
}.also { mainHandler.postDelayed(it, HIGHLIGHT_DURATION_MS) }
}
}
}
}
@@ -186,11 +218,16 @@ class SlaveActivity : BaseActivity() {
override fun onDestroy() {
ScaleServiceManager.onMasterConnectionChanged = null
WeightUtil.removeWeightListener(TAG)
clearHighlightRunnable?.let { mainHandler.removeCallbacks(it) }
super.onDestroy()
}
companion object {
const val TAG = "SlaveActivity"
/** 重量增加阈值(克),超过此值才触发高亮 */
private const val WEIGHT_DELTA_THRESHOLD = 10.0
/** 高亮自动恢复时间(毫秒) */
private const val HIGHLIGHT_DURATION_MS = 15_000L
}
/**