refactor(layout): 优化布局尺寸计算逻辑并提取公共工具类

- 添加 SizeTool 工具类统一管理 Flexbox 布局尺寸计算
- 在 MasterScaleActivity 中使用 SizeTool 替代硬编码计算
- 在 SeasoningConfigFragment 中使用 SizeTool 重构尺寸计算
- 在 SlaveActivity 中应用统一的尺寸计算方法
- 更新 Seasoning18GridAdapter 和 Seasoning22GridAdapter 使用现代化布局参数设置
- 调整 fragment_seasoning_config.xml 中的边距和内边距数值
- 为布局文件添加 tools:itemCount 属性支持预览功能
This commit is contained in:
2026-04-22 09:28:07 +08:00
parent b6b5088107
commit 97b357850c
8 changed files with 59 additions and 37 deletions
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
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
@@ -25,7 +26,8 @@ import com.shuwei.dish.match.utils.ext.dp
*/ */
class Seasoning18GridAdapter( class Seasoning18GridAdapter(
private val showNameOnly: Boolean = false, private val showNameOnly: Boolean = false,
private val showAddress: Boolean = false private val showAddress: Boolean = false,
private val leftRightSpace: Int = 10.dp
) : BaseQuickAdapter<ScaleData, Seasoning18GridAdapter.VH>(mutableListOf()) { ) : BaseQuickAdapter<ScaleData, Seasoning18GridAdapter.VH>(mutableListOf()) {
/** 空位哨兵,address=0 表示无效 */ /** 空位哨兵,address=0 表示无效 */
@@ -47,12 +49,12 @@ class Seasoning18GridAdapter(
val b = ListItemScale22RowBinding.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 margin = if (viewType == 0) 12.dp else 2.dp
val screenWidth = parent.resources.displayMetrics.widthPixels val screenWidth = parent.resources.displayMetrics.widthPixels
val cellSize = (screenWidth - 6 * margin * 2 - 10.dp) / 6 val cellSize = (screenWidth - 6 * margin * 2 - leftRightSpace) / 6
(b.root.layoutParams as? ViewGroup.MarginLayoutParams)?.also { b.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
it.width = cellSize width = cellSize
it.height = cellSize height = cellSize
if (viewType == 0) it.setMargins(margin, 0, margin, 2.dp) if (viewType == 0) setMargins(margin, 0, margin, 2.dp)
else it.setMargins(margin, margin, margin, margin) else setMargins(margin, margin, margin, margin)
} }
val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt() val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt()
b.tvAddress.textSize = (baseSp * 0.14f).coerceIn(8f, 12f) b.tvAddress.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.updateLayoutParams
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
@@ -51,7 +52,7 @@ class Seasoning22GridAdapter(
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false) val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
val cellSize = if (viewType == 1) largeSize else smallSize val cellSize = if (viewType == 1) largeSize else smallSize
(b.root.layoutParams as? FlexboxLayoutManager.LayoutParams)?.apply { b.root.updateLayoutParams<FlexboxLayoutManager.LayoutParams> {
width = cellSize width = cellSize
height = cellSize height = cellSize
setMargins(2.dp, 2.dp, 2.dp, 2.dp) setMargins(2.dp, 2.dp, 2.dp, 2.dp)
@@ -33,6 +33,7 @@ import com.shuwei.dish.match.scale.ScaleServiceManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import com.shuwei.dish.match.utils.NetworkUtil import com.shuwei.dish.match.utils.NetworkUtil
import com.shuwei.dish.match.utils.SizeTool
import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.dp import com.shuwei.dish.match.utils.ext.dp
import com.shuwei.dish.match.utils.ext.toast import com.shuwei.dish.match.utils.ext.toast
@@ -51,7 +52,7 @@ private const val VIEW_TYPE_SCALE1 = 3
class MasterScaleActivity : BaseActivity() { class MasterScaleActivity : BaseActivity() {
private lateinit var binding: ActivityMasterScaleBinding private lateinit var binding: ActivityMasterScaleBinding
private val size by lazy { SizeTool.getFlexLayoutSize(10.dp) }
private data class DeviceGroup( private data class DeviceGroup(
val deviceId: String, val deviceId: String,
val ip: String, val ip: String,
@@ -357,12 +358,7 @@ class MasterScaleActivity : BaseActivity() {
b.tvDeviceLabel.text = "设备:${group.deviceId}" b.tvDeviceLabel.text = "设备:${group.deviceId}"
if (innerAdapter == null) { if (innerAdapter == null) {
val screenWidth = resources.displayMetrics.widthPixels b.rvScales.layoutParams = b.rvScales.layoutParams.also { it.height = size.rvHeight }
val usable = screenWidth - 8 * 4.dp - 10.dp
val smallSize = usable / 9
val largeSize = (usable - smallSize * 6) / 2
val rvHeight = smallSize * 3 + 3 * 4.dp
b.rvScales.layoutParams = b.rvScales.layoutParams.also { it.height = rvHeight }
b.rvScales.layoutManager = FlexboxLayoutManager(b.root.context).apply { b.rvScales.layoutManager = FlexboxLayoutManager(b.root.context).apply {
flexDirection = FlexDirection.COLUMN flexDirection = FlexDirection.COLUMN
flexWrap = FlexWrap.WRAP flexWrap = FlexWrap.WRAP
@@ -370,8 +366,8 @@ class MasterScaleActivity : BaseActivity() {
} }
b.rvScales.itemAnimator = null b.rvScales.itemAnimator = null
innerAdapter = Seasoning22GridAdapter( innerAdapter = Seasoning22GridAdapter(
largeSize, size.largeSize,
smallSize, size.smallSize,
showNameOnly = false, showNameOnly = false,
showAddress = true showAddress = true
).apply { ).apply {
@@ -27,6 +27,7 @@ import com.shuwei.dish.match.scale.ScaleData
import com.shuwei.dish.match.scale.ScaleDeviceConfig import com.shuwei.dish.match.scale.ScaleDeviceConfig
import com.shuwei.dish.match.scale.ScaleServiceManager import com.shuwei.dish.match.scale.ScaleServiceManager
import com.shuwei.dish.match.utils.NetworkUtil import com.shuwei.dish.match.utils.NetworkUtil
import com.shuwei.dish.match.utils.SizeTool
import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.dp import com.shuwei.dish.match.utils.ext.dp
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -61,6 +62,7 @@ class SlaveActivity : BaseActivity() {
private val mainHandler = Handler(Looper.getMainLooper()) private val mainHandler = Handler(Looper.getMainLooper())
/** 当前高亮清除任务,新高亮触发时取消旧任务 */ /** 当前高亮清除任务,新高亮触发时取消旧任务 */
private var clearHighlightRunnable: Runnable? = null private var clearHighlightRunnable: Runnable? = null
private val size by lazy { SizeTool.getFlexLayoutSize(10.dp) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -90,13 +92,8 @@ class SlaveActivity : BaseActivity() {
binding.rvScaleList.itemAnimator = null binding.rvScaleList.itemAnimator = null
when (GlobalData.deviceId) { when (GlobalData.deviceId) {
ScaleDeviceConfig.DEVICE_ID_22 -> { ScaleDeviceConfig.DEVICE_ID_22 -> {
val screenWidth = resources.displayMetrics.widthPixels
val usable = screenWidth - 8 * 4.dp - 10.dp
val smallSize = usable / 9
val largeSize = (usable - smallSize * 6) / 2
val rvHeight = smallSize * 3 + 3 * 4.dp
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> { binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> {
height = rvHeight height = size.rvHeight
weight = 0f weight = 0f
topMargin = 20.dp topMargin = 20.dp
} }
@@ -105,7 +102,7 @@ class SlaveActivity : BaseActivity() {
flexWrap = FlexWrap.WRAP flexWrap = FlexWrap.WRAP
alignItems = AlignItems.FLEX_START alignItems = AlignItems.FLEX_START
} }
scale22Adapter = Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = false).also { scale22Adapter = Seasoning22GridAdapter(size.largeSize, size.smallSize, showNameOnly = false).also {
it.onItemClick = { scale, _ -> showTareDialog(scale.address) } it.onItemClick = { scale, _ -> showTareDialog(scale.address) }
} }
binding.rvScaleList.adapter = scale22Adapter binding.rvScaleList.adapter = scale22Adapter
@@ -25,6 +25,7 @@ import com.shuwei.dish.match.scale.ScaleEvent
import com.shuwei.dish.match.scale.ScaleServiceManager import com.shuwei.dish.match.scale.ScaleServiceManager
import com.shuwei.dish.match.scale.ScaleEvent.SlotConfig import com.shuwei.dish.match.scale.ScaleEvent.SlotConfig
import com.shuwei.dish.match.ui.SettingActivity import com.shuwei.dish.match.ui.SettingActivity
import com.shuwei.dish.match.utils.SizeTool
import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.dp import com.shuwei.dish.match.utils.ext.dp
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -50,7 +51,7 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
// private lateinit var appViewModel: AppViewModel // private lateinit var appViewModel: AppViewModel
private val adapter22 by lazy { buildAdapter22() } private val adapter22 by lazy { buildAdapter22() }
private val adapter18 by lazy { Seasoning18GridAdapter(showNameOnly = true) } private val adapter18 by lazy { Seasoning18GridAdapter(showNameOnly = true, leftRightSpace = 20.dp) }
/** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */ /** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */
private val weightSnapshot = mutableMapOf<String, Double>() private val weightSnapshot = mutableMapOf<String, Double>()
@@ -150,24 +151,23 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
// appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java] // appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
// } // }
private val size by lazy { SizeTool.getFlexLayoutSize(20.dp) }
/** 构建上层(22格)Adapter,需要先计算格子尺寸 */ /** 构建上层(22格)Adapter,需要先计算格子尺寸 */
private fun buildAdapter22(): Seasoning22GridAdapter { private fun buildAdapter22(): Seasoning22GridAdapter {
val usable = resources.displayMetrics.widthPixels - 8 * 4.dp - 10.dp return Seasoning22GridAdapter(
val smallSize = usable / 9 largeSize = size.largeSize,
val largeSize = (usable - smallSize * 6) / 2 smallSize = size.smallSize,
return Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = true) showNameOnly = true
)
} }
/** 配置两个 RecyclerView */ /** 配置两个 RecyclerView */
private fun setupRecyclerViews() { private fun setupRecyclerViews() {
// 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式 // 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式
// rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致 // rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致
val screenWidth = resources.displayMetrics.widthPixels
val usable = screenWidth - 8 * 4.dp - 10.dp
val smallSize = usable / 9
val rvTopHeight = smallSize * 3 + 3 * 4.dp
binding.rvTop.apply { binding.rvTop.apply {
layoutParams = layoutParams.also { it.height = rvTopHeight } layoutParams = layoutParams.also { it.height = size.rvHeight }
layoutManager = FlexboxLayoutManager(requireContext()).apply { layoutManager = FlexboxLayoutManager(requireContext()).apply {
flexDirection = FlexDirection.COLUMN flexDirection = FlexDirection.COLUMN
flexWrap = FlexWrap.WRAP flexWrap = FlexWrap.WRAP
@@ -0,0 +1,25 @@
package com.shuwei.dish.match.utils
import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.utils.ext.dp
data class FlexLayoutSize(
val smallSize: Int,
val largeSize: Int,
val rvHeight: Int
)
object SizeTool {
fun getFlexLayoutSize(leftRightSpace: Int = 10.dp): FlexLayoutSize {
// 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式
// rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致
val screenWidth = BaseApp.instance!!.resources.displayMetrics.widthPixels
val usable = screenWidth - 8 * 4.dp - leftRightSpace
val smallSize = usable / 9
val largeSize = (usable - smallSize * 6) / 2
val rvHeight = smallSize * 3 + 3 * 4.dp
return FlexLayoutSize(smallSize, largeSize, rvHeight)
}
}
@@ -59,6 +59,7 @@
app:layout_constraintTop_toBottomOf="@id/tvConnectionStatus" app:layout_constraintTop_toBottomOf="@id/tvConnectionStatus"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:overScrollMode="never" android:overScrollMode="never"
tools:itemCount="4"
tools:listitem="@layout/list_type_scale22"/> tools:listitem="@layout/list_type_scale22"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@@ -8,9 +8,9 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="0dp" android:layout_marginStart="10dp"
android:layout_marginEnd="0dp" android:layout_marginEnd="10dp"
android:paddingBottom="20dp" android:paddingBottom="10dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:background="@drawable/shape_white_30_corners" android:background="@drawable/shape_white_30_corners"
android:orientation="vertical"> android:orientation="vertical">