diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/Scale18GridAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/Scale18GridAdapter.kt index d877902..54168b0 100644 --- a/app/src/main/java/com/shuwei/dish/match/adapter/Scale18GridAdapter.kt +++ b/app/src/main/java/com/shuwei/dish/match/adapter/Scale18GridAdapter.kt @@ -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(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(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) { 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 index 09775fd..9b9e550 100644 --- a/app/src/main/java/com/shuwei/dish/match/adapter/Scale22GridAdapter.kt +++ b/app/src/main/java/com/shuwei/dish/match/adapter/Scale22GridAdapter.kt @@ -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) { 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 8496e4b..a7a4018 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 @@ -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() + /** 主线程 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 } /**