feat(activity): 为子设备 SlaveActivity 添加调料秤重量增加高亮提醒功能
检测本机秤稳定后重量增加超过10g,高亮对应格子(红底白字),15秒后自动恢复
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
package com.shuwei.dish.match.adapter
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
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.databinding.ListItemScale22RowBinding
|
||||||
import com.shuwei.dish.match.scale.ScaleData
|
import com.shuwei.dish.match.scale.ScaleData
|
||||||
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
||||||
@@ -25,6 +27,9 @@ class Scale18GridAdapter : BaseQuickAdapter<ScaleData, Scale18GridAdapter.VH>(mu
|
|||||||
/** 用 address=0 的哨兵表示空位 */
|
/** 用 address=0 的哨兵表示空位 */
|
||||||
private val empty = ScaleData("", 0, 0.0, -1, 0)
|
private val empty = ScaleData("", 0, 0.0, -1, 0)
|
||||||
|
|
||||||
|
/** 当前高亮的格子位置,-1 表示无高亮 */
|
||||||
|
private var highlightedPosition: Int = -1
|
||||||
|
|
||||||
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
|
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
|
||||||
var onItemClick: ((ScaleData) -> Unit)? = null
|
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.tvAddr.text = if (valid) "秤${item!!.address}" else ""
|
||||||
holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
|
holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
|
||||||
holder.b.tvState.text = if (valid) stateStr(item!!.state) 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) {
|
private fun stateStr(state: Int) = when (state) {
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
import com.google.android.flexbox.FlexboxLayoutManager
|
import com.google.android.flexbox.FlexboxLayoutManager
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
|
import com.shuwei.dish.match.databinding.ListItemScale22RowBinding
|
||||||
import com.shuwei.dish.match.scale.ScaleData
|
import com.shuwei.dish.match.scale.ScaleData
|
||||||
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
||||||
@@ -32,6 +34,9 @@ class Scale22GridAdapter(
|
|||||||
/** 用 address=0 的哨兵表示空位 */
|
/** 用 address=0 的哨兵表示空位 */
|
||||||
private val empty = ScaleData("", 0, 0.0, -1, 0)
|
private val empty = ScaleData("", 0, 0.0, -1, 0)
|
||||||
|
|
||||||
|
/** 当前高亮的格子位置,-1 表示无高亮 */
|
||||||
|
private var highlightedPosition: Int = -1
|
||||||
|
|
||||||
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
|
/** 点击回调,在 onCreateViewHolder 中绑定,不受 notifyItemChanged 影响 */
|
||||||
var onItemClick: ((ScaleData) -> Unit)? = null
|
var onItemClick: ((ScaleData) -> Unit)? = null
|
||||||
|
|
||||||
@@ -93,6 +98,38 @@ class Scale22GridAdapter(
|
|||||||
holder.b.tvAddr.text = if (valid) "秤${item!!.address}" else ""
|
holder.b.tvAddr.text = if (valid) "秤${item!!.address}" else ""
|
||||||
holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
|
holder.b.tvWeight.text = if (valid) "${item!!.weight}g" else ""
|
||||||
holder.b.tvState.text = if (valid) stateStr(item!!.state) 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) {
|
private fun stateStr(state: Int) = when (state) {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@@ -45,6 +47,13 @@ class SlaveActivity : BaseActivity() {
|
|||||||
/** 已连接的主设备数量(有连接即代表主设备在线) */
|
/** 已连接的主设备数量(有连接即代表主设备在线) */
|
||||||
private var masterConnected = false
|
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?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivitySlaveBinding.inflate(layoutInflater)
|
binding = ActivitySlaveBinding.inflate(layoutInflater)
|
||||||
@@ -134,9 +143,19 @@ class SlaveActivity : BaseActivity() {
|
|||||||
/**
|
/**
|
||||||
* 监听本机 WeightUtil 回调,实时刷新秤列表
|
* 监听本机 WeightUtil 回调,实时刷新秤列表
|
||||||
* 22/18个秤走网格 adapter,其余走线性列表
|
* 22/18个秤走网格 adapter,其余走线性列表
|
||||||
|
* 秤稳定且重量增加超过阈值时,高亮对应格子,15秒后自动恢复
|
||||||
*/
|
*/
|
||||||
private fun listenLocalScales() {
|
private fun listenLocalScales() {
|
||||||
WeightUtil.addWeightListener(TAG) { address, state, weight ->
|
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 {
|
runOnUiThread {
|
||||||
when {
|
when {
|
||||||
scale22Adapter != null -> {
|
scale22Adapter != null -> {
|
||||||
@@ -167,6 +186,19 @@ class SlaveActivity : BaseActivity() {
|
|||||||
linearAdapter.submitList(list)
|
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() {
|
override fun onDestroy() {
|
||||||
ScaleServiceManager.onMasterConnectionChanged = null
|
ScaleServiceManager.onMasterConnectionChanged = null
|
||||||
WeightUtil.removeWeightListener(TAG)
|
WeightUtil.removeWeightListener(TAG)
|
||||||
|
clearHighlightRunnable?.let { mainHandler.removeCallbacks(it) }
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "SlaveActivity"
|
const val TAG = "SlaveActivity"
|
||||||
|
/** 重量增加阈值(克),超过此值才触发高亮 */
|
||||||
|
private const val WEIGHT_DELTA_THRESHOLD = 10.0
|
||||||
|
/** 高亮自动恢复时间(毫秒) */
|
||||||
|
private const val HIGHLIGHT_DURATION_MS = 15_000L
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user