From 9ba6443f4ff2916c6e20c5d7085738db7bf572c3 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Wed, 22 Apr 2026 14:55:09 +0800 Subject: [PATCH] =?UTF-8?q?refactor(setting):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E9=9D=A2=E7=95=8C=E9=9D=A2=E5=92=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将底部导航菜单替换为三个独立的功能卡片布局 - 添加餐品模式、调料区设置和食材采样功能入口 - 移除原有的Fragment容器和标签页切换逻辑 - 更新CollectFragment以使用新的SingleFragmentActivity架构 - 修改相机权限检查逻辑并添加权限拒绝提示对话框 - 简化DeviceConfigFragment和SeasoningConfigFragment的依赖导入 - 在设置页面添加当前模式显示和跳转功能 - 重构调料配置页面的日志记录和高亮逻辑 --- .../shuwei/dish/match/ui/SettingActivity.kt | 430 ++++++++++-------- .../dish/match/ui/SingleFragmentActivity.kt | 35 +- .../dish/match/ui/fragment/CollectFragment.kt | 55 ++- .../match/ui/fragment/DeviceConfigFragment.kt | 43 +- .../ui/fragment/SeasoningConfigFragment.kt | 144 +++--- .../res/drawable-xxxhdpi/ic_arrow_right2.png | Bin 0 -> 4758 bytes app/src/main/res/layout/activity_setting.xml | 198 +++++--- 7 files changed, 561 insertions(+), 344 deletions(-) create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_arrow_right2.png diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SettingActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SettingActivity.kt index 2587ed5..58eee9c 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/SettingActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/SettingActivity.kt @@ -2,33 +2,19 @@ package com.shuwei.dish.match.ui import android.Manifest import android.annotation.SuppressLint +import android.content.Intent import android.content.pm.PackageManager -import android.graphics.Color import android.net.Uri import android.os.Build import android.os.Bundle -import android.view.ViewGroup -import androidx.appcompat.widget.AppCompatButton +import android.provider.Settings import androidx.core.content.ContextCompat -import androidx.core.graphics.toColorInt -import androidx.fragment.app.Fragment -import androidx.camera.view.PreviewView -import androidx.core.view.updateLayoutParams -import com.shuwei.dish.match.R import com.shuwei.dish.match.base.BaseActivity -import com.shuwei.dish.match.base.DeviceRole -import com.shuwei.dish.match.base.GlobalData import com.shuwei.dish.match.databinding.ActivitySettingBinding -import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding -import com.shuwei.dish.match.ui.fragment.CollectFragment -import com.shuwei.dish.match.ui.fragment.DeviceConfigFragment -import com.shuwei.dish.match.ui.fragment.SeasoningConfigFragment -import com.shuwei.dish.match.utils.CameraUtils +import com.shuwei.dish.match.dialog.CommonDialog import com.shuwei.dish.match.utils.SpTool -import com.shuwei.dish.match.utils.ext.dp +import com.shuwei.dish.match.utils.ext.clickWithDebounce import com.shuwei.dish.match.utils.ext.gone -import com.shuwei.dish.match.utils.ext.startActivity -import com.shuwei.dish.match.utils.ext.toast import com.shuwei.dish.match.utils.ext.visible /** @@ -42,10 +28,10 @@ class SettingActivity : BaseActivity() { } private lateinit var binding: ActivitySettingBinding - private val cameraUtils: CameraUtils by lazy { - CameraUtils(this) - } - private lateinit var previewView: PreviewView +// private val cameraUtils: CameraUtils by lazy { +// CameraUtils(this) +// } +// private lateinit var previewView: PreviewView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -55,104 +41,51 @@ class SettingActivity : BaseActivity() { setTitleBar(titleBarAction = { it.visible() }, titleAction = { - it.text = "设置" + it.text = "设备设置" }, rightIconActon = { it.gone() }) - // 默认显示设备配置Fragment - if (savedInstanceState == null) { - showDeviceConfigFragment() - } + initView() - initUI() +// // 默认显示设备配置Fragment +// if (savedInstanceState == null) { +// showDeviceConfigFragment() +// } +// +// initUI() } - /** - * 初始化UI和事件监听 - */ - private fun initUI() { - // 设备配置按钮点击事件 - binding.btnDeviceConfig.setOnClickListener { - showDeviceConfigFragment() - loadTabStyle(button = binding.btnDeviceConfig, isSelected = true) - loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) - loadTabStyle(button = binding.btnFoodCollect, isSelected = false) + private fun initView() { + binding.tvCurrentMode.text = when (SpTool.cookMode) { + 0 -> "当前:制作模式" + 1 -> "当前:采样模式" + else -> "当前:未知模式" } - - // 调料配置按钮点击事件 - binding.btnSeasoningConfig.setOnClickListener { - showSeasoningConfigFragment() - - loadTabStyle(button = binding.btnDeviceConfig, isSelected = false) - loadTabStyle(button = binding.btnSeasoningConfig, isSelected = true) - loadTabStyle(button = binding.btnFoodCollect, isSelected = false) + binding.llCookMode.clickWithDebounce { + SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.COOK_MODE) } - - // 菜品采集按钮点击事件 - binding.btnFoodCollect.setOnClickListener { - checkCameraPermissionAndShowFragment() - - loadTabStyle(button = binding.btnDeviceConfig, isSelected = false) - loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) - loadTabStyle(button = binding.btnFoodCollect, isSelected = true) + binding.llSeasoningConfig.clickWithDebounce { + SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.SEASONING_CONFIG) } - - // 主设备显示「秤数据监控」入口 - if (GlobalData.deviceRole == DeviceRole.MASTER) { - binding.btnScaleMonitor.visible() - binding.btnScaleMonitor.setOnClickListener { - startActivity() - } + binding.llFoodCollect.clickWithDebounce { + checkCameraPermission() } - - // 初始化按钮颜色(默认设备配置为选中状态) - - loadTabStyle(button = binding.btnDeviceConfig, isSelected = true) - loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) - loadTabStyle(button = binding.btnFoodCollect, isSelected = false) } -// /** 刷新角色按钮文字 */ -// private fun updateRoleButtonText() { -// val roleLabel = if (GlobalData.deviceRole == DeviceRole.MASTER) "主设备" else "子设备" -// binding.btnDeviceRole.text = "设备角色:$roleLabel" -// } - - /** - * 加载顶部Tab按钮样式 - * - * @param button 按钮 - * @param isSelected 是否选中 - */ - private fun loadTabStyle(button: AppCompatButton, isSelected: Boolean) { - button.apply { - if (isSelected){ - // 选中 - setTextColor(Color.WHITE) - textSize = 28f - setTypeface(null, android.graphics.Typeface.BOLD) - background = ContextCompat.getDrawable(this@SettingActivity, R.drawable.bg_btn_underline) - } else { - // 未选中 - setTextColor("#5E7585".toColorInt()) - textSize = 26f - setTypeface(null, android.graphics.Typeface.NORMAL) - background = null - } - } + private fun openCollectPage() { + SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.FOOD_COLLECT) } /** * 检查相机权限并显示 CollectFragment */ @SuppressLint("ObsoleteSdkInt") - private fun checkCameraPermissionAndShowFragment() { - val collectFragment = fragmentList[2] + private fun checkCameraPermission() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // Android 6.0 以下,直接显示 Fragment - showFragment(collectFragment) + // Android 6.0 以下,直接打开 + openCollectPage() return } if (ContextCompat.checkSelfPermission( @@ -160,109 +93,228 @@ class SettingActivity : BaseActivity() { Manifest.permission.CAMERA ) == PackageManager.PERMISSION_GRANTED ) { - // 权限已授予,直接显示 Fragment - showFragment(collectFragment) + // 权限已授予,直接打开 + openCollectPage() } else { // 权限未授予,申请权限 requestPermission(Manifest.permission.CAMERA) { isGranted -> if (isGranted) { - // 权限已授予,显示 CollectFragment - showFragment(collectFragment) + // 权限已授予,直接打开 + openCollectPage() } else { // 权限被拒绝 - toast("暂无相机权限,无法使用菜品采集功能") + showNotGrantedCameraPermissionDialog() } } } } - /** - * 初始化相机 - * @param container 相机预览容器 - */ - fun initCamera(container: ViewGroup) { - cameraUtils.initCamera() - val previewBinding = - LayoutCameraPreviewBinding.inflate(layoutInflater, container) - previewView = previewBinding.previewView.also { - it.updateLayoutParams { - width = 456.dp - height = 342.dp - } - } - cameraUtils.setPreviewController(previewView) - } - - /** - * Activity 恢复时绑定相机 - */ - override fun onResume() { - super.onResume() - cameraUtils.bind() - } - - /** - * Activity 暂停时解绑相机 - */ - override fun onPause() { - super.onPause() - cameraUtils.unbind() - } - - /** - * 提供给 Fragment 调用的拍照方法 - */ - fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = {}) { - cameraUtils.takePhoto(succCallback = succCallback, failCallback = failCallback) - } - - /** - * 显示设备切换Fragment - */ - private fun showDeviceConfigFragment() { - showFragment(fragmentList[0]) - } - - /** - * 显示设调料配置Fragment - */ - private fun showSeasoningConfigFragment() { - showFragment(fragmentList[1]) - } - - private val fragmentList = mutableListOf().apply { - add(DeviceConfigFragment()) - add(SeasoningConfigFragment()) - add(CollectFragment()) - } - - /** - * 显示指定的 Fragment - * 使用 add/show/hide 方式管理 Fragment,避免重复创建 - * 已添加的 Fragment 直接显示,未添加的 Fragment 先添加再显示 - */ - private fun showFragment(fragment: Fragment) { - runCatching { - supportFragmentManager.beginTransaction().apply { - // 如果 Fragment 还未添加到容器中,则添加 - if (!fragment.isAdded) { - add(binding.fragmentContainer.id, fragment) - } else { - // 已添加过,直接显示 - show(fragment) + private fun showNotGrantedCameraPermissionDialog() { + CommonDialog(this) + .setTitle("温馨提示") + .setContent("暂无相机权限,无法使用菜品采集功能,请确认是否同意开始权限?") + .setNegativeButton("不同意") + .setPositiveButton("同意") { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", packageName, null) } - - // 隐藏其他 Fragment - fragmentList.forEach { otherFragment -> - if (otherFragment != fragment && otherFragment.isAdded) { - hide(otherFragment) - } + startActivity(intent) { + checkCameraPermission() } - - commit() } - }.onFailure { - it.printStackTrace() - } + .show() } + +// +// /** +// * 初始化UI和事件监听 +// */ +// private fun initUI() { +// // 设备配置按钮点击事件 +// binding.btnDeviceConfig.setOnClickListener { +// showDeviceConfigFragment() +// +// loadTabStyle(button = binding.btnDeviceConfig, isSelected = true) +// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) +// loadTabStyle(button = binding.btnFoodCollect, isSelected = false) +// } +// +// // 调料配置按钮点击事件 +// binding.btnSeasoningConfig.setOnClickListener { +// showSeasoningConfigFragment() +// +// loadTabStyle(button = binding.btnDeviceConfig, isSelected = false) +// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = true) +// loadTabStyle(button = binding.btnFoodCollect, isSelected = false) +// } +// +// // 菜品采集按钮点击事件 +// binding.btnFoodCollect.setOnClickListener { +// checkCameraPermissionAndShowFragment() +// +// loadTabStyle(button = binding.btnDeviceConfig, isSelected = false) +// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) +// loadTabStyle(button = binding.btnFoodCollect, isSelected = true) +// } +// +// // 主设备显示「秤数据监控」入口 +// if (GlobalData.deviceRole == DeviceRole.MASTER) { +// binding.btnScaleMonitor.visible() +// binding.btnScaleMonitor.setOnClickListener { +// startActivity() +// } +// } +// +// // 初始化按钮颜色(默认设备配置为选中状态) +// +// loadTabStyle(button = binding.btnDeviceConfig, isSelected = true) +// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false) +// loadTabStyle(button = binding.btnFoodCollect, isSelected = false) +// } +// +// /** +// * 加载顶部Tab按钮样式 +// * +// * @param button 按钮 +// * @param isSelected 是否选中 +// */ +// private fun loadTabStyle(button: AppCompatButton, isSelected: Boolean) { +// button.apply { +// if (isSelected){ +// // 选中 +// setTextColor(Color.WHITE) +// textSize = 28f +// setTypeface(null, android.graphics.Typeface.BOLD) +// background = ContextCompat.getDrawable(this@SettingActivity, R.drawable.bg_btn_underline) +// } else { +// // 未选中 +// setTextColor("#5E7585".toColorInt()) +// textSize = 26f +// setTypeface(null, android.graphics.Typeface.NORMAL) +// background = null +// } +// } +// } +// +// /** +// * 检查相机权限并显示 CollectFragment +// */ +// @SuppressLint("ObsoleteSdkInt") +// private fun checkCameraPermissionAndShowFragment() { +// val collectFragment = fragmentList[2] +// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { +// // Android 6.0 以下,直接显示 Fragment +// showFragment(collectFragment) +// return +// } +// if (ContextCompat.checkSelfPermission( +// this, +// Manifest.permission.CAMERA +// ) == PackageManager.PERMISSION_GRANTED +// ) { +// // 权限已授予,直接显示 Fragment +// showFragment(collectFragment) +// } else { +// // 权限未授予,申请权限 +// requestPermission(Manifest.permission.CAMERA) { isGranted -> +// if (isGranted) { +// // 权限已授予,显示 CollectFragment +// showFragment(collectFragment) +// } else { +// // 权限被拒绝 +// toast("暂无相机权限,无法使用菜品采集功能") +// } +// } +// } +// } +// +// /** +// * 初始化相机 +// * @param container 相机预览容器 +// */ +// fun initCamera(container: ViewGroup) { +// cameraUtils.initCamera() +// val previewBinding = +// LayoutCameraPreviewBinding.inflate(layoutInflater, container) +// previewView = previewBinding.previewView.also { +// it.updateLayoutParams { +// width = 456.dp +// height = 342.dp +// } +// } +// cameraUtils.setPreviewController(previewView) +// } +// +// /** +// * Activity 恢复时绑定相机 +// */ +// override fun onResume() { +// super.onResume() +// cameraUtils.bind() +// } +// +// /** +// * Activity 暂停时解绑相机 +// */ +// override fun onPause() { +// super.onPause() +// cameraUtils.unbind() +// } +// +// /** +// * 提供给 Fragment 调用的拍照方法 +// */ +// fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = {}) { +// cameraUtils.takePhoto(succCallback = succCallback, failCallback = failCallback) +// } +// +// /** +// * 显示设备切换Fragment +// */ +// private fun showDeviceConfigFragment() { +// showFragment(fragmentList[0]) +// } +// +// /** +// * 显示设调料配置Fragment +// */ +// private fun showSeasoningConfigFragment() { +// showFragment(fragmentList[1]) +// } +// +// private val fragmentList = mutableListOf().apply { +// add(DeviceConfigFragment()) +// add(SeasoningConfigFragment()) +// add(CollectFragment()) +// } +// +// /** +// * 显示指定的 Fragment +// * 使用 add/show/hide 方式管理 Fragment,避免重复创建 +// * 已添加的 Fragment 直接显示,未添加的 Fragment 先添加再显示 +// */ +// private fun showFragment(fragment: Fragment) { +// runCatching { +// supportFragmentManager.beginTransaction().apply { +// // 如果 Fragment 还未添加到容器中,则添加 +// if (!fragment.isAdded) { +// add(binding.fragmentContainer.id, fragment) +// } else { +// // 已添加过,直接显示 +// show(fragment) +// } +// +// // 隐藏其他 Fragment +// fragmentList.forEach { otherFragment -> +// if (otherFragment != fragment && otherFragment.isAdded) { +// hide(otherFragment) +// } +// } +// +// commit() +// } +// }.onFailure { +// it.printStackTrace() +// } +// } } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SingleFragmentActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SingleFragmentActivity.kt index 5db66e9..fcf44f1 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/SingleFragmentActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/SingleFragmentActivity.kt @@ -17,15 +17,22 @@ import com.shuwei.dish.match.utils.ext.visible */ class SingleFragmentActivity : BaseActivity() { + interface LifecycleCallback { + fun onActivityResume() + fun onActivityPause() + } + /** * 支持的页面类型枚举 * 新增页面时在此追加枚举值,并在 [createFragment] 中补充对应分支 */ enum class PageType { /** 菜品采集页 */ - COLLECT, + FOOD_COLLECT, + /** 设备配置页 */ - DEVICE_CONFIG, + COOK_MODE, + /** 调料配置页 */ SEASONING_CONFIG, } @@ -46,6 +53,11 @@ class SingleFragmentActivity : BaseActivity() { } } + private var lifecycleCallback: LifecycleCallback? = null + fun setLifecycleCallback(callback: LifecycleCallback) { + lifecycleCallback = callback + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHeaderBackground() @@ -80,8 +92,8 @@ class SingleFragmentActivity : BaseActivity() { * 根据页面类型返回对应标题文本 */ private fun getTitleForPage(pageType: PageType): String = when (pageType) { - PageType.COLLECT -> "菜品采集" - PageType.DEVICE_CONFIG -> "设备配置" + PageType.FOOD_COLLECT -> "菜品采集" + PageType.COOK_MODE -> "设备配置" PageType.SEASONING_CONFIG -> "调料配置" } @@ -89,8 +101,19 @@ class SingleFragmentActivity : BaseActivity() { * 根据页面类型创建对应 Fragment 实例 */ private fun createFragment(pageType: PageType): Fragment = when (pageType) { - PageType.COLLECT -> CollectFragment() - PageType.DEVICE_CONFIG -> DeviceConfigFragment() + PageType.FOOD_COLLECT -> CollectFragment() + PageType.COOK_MODE -> DeviceConfigFragment() PageType.SEASONING_CONFIG -> SeasoningConfigFragment() } + + override fun onResume() { + super.onResume() + lifecycleCallback?.onActivityResume() + } + + override fun onPause() { + super.onPause() + lifecycleCallback?.onActivityPause() + } + } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/CollectFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/CollectFragment.kt index d4d01c3..d6d73b4 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/CollectFragment.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/CollectFragment.kt @@ -10,24 +10,29 @@ import android.view.View import android.view.ViewGroup import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager +import androidx.camera.view.PreviewView +import androidx.core.view.updateLayoutParams import androidx.recyclerview.widget.GridLayoutManager import com.shuwei.dish.match.R import com.shuwei.dish.match.adapter.FoodCollectionAdapter import com.shuwei.dish.match.base.BaseFragment import com.shuwei.dish.match.databinding.FragmentCollectBinding +import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding import com.shuwei.dish.match.dialog.Loading import com.shuwei.dish.match.objbox.FoodCollectionBean import com.shuwei.dish.match.objbox.FoodModule -import com.shuwei.dish.match.ui.SettingActivity +import com.shuwei.dish.match.ui.SingleFragmentActivity import com.shuwei.dish.match.utils.BitmapSaver +import com.shuwei.dish.match.utils.CameraUtils import com.shuwei.dish.match.utils.Debouncer import com.shuwei.dish.match.utils.ImageUtil import com.shuwei.dish.match.utils.LogSaveUtil import com.shuwei.dish.match.utils.ext.clickWithDebounce +import com.shuwei.dish.match.utils.ext.dp import com.shuwei.dish.match.utils.ext.toast @SuppressLint("NotifyDataSetChanged") -class CollectFragment : BaseFragment() { +class CollectFragment : BaseFragment(){ companion object { private const val TAG = "CollectFragment" @@ -58,7 +63,8 @@ class CollectFragment : BaseFragment() { // } // } private val debouncer = Debouncer(2000) - private lateinit var settingActivity: SettingActivity +// private lateinit var settingActivity: SettingActivity + private lateinit var currentActivity: SingleFragmentActivity private val collectionAdapter: FoodCollectionAdapter by lazy { FoodCollectionAdapter(foodCollectionList).apply { @@ -168,7 +174,7 @@ class CollectFragment : BaseFragment() { return } showWaitingDialog("采集中……") - settingActivity.takePhoto(succCallback = cameraCallback, failCallback = { errMsg -> + cameraUtils.takePhoto(succCallback = cameraCallback, failCallback = { errMsg -> hideWaitingDialog() // toast("拍照异常,请重新操作") // if (cameraErrorCount >= 10) { @@ -183,9 +189,18 @@ class CollectFragment : BaseFragment() { } override fun initialize() { - settingActivity = activity as SettingActivity + currentActivity = activity as SingleFragmentActivity // 首次显示 CollectFragment 时初始化相机 - settingActivity.initCamera(binding.flCameraPreview) + initCamera(binding.flCameraPreview) + currentActivity.setLifecycleCallback(object : SingleFragmentActivity.LifecycleCallback { + override fun onActivityResume() { + cameraUtils.bind() + } + + override fun onActivityPause() { + cameraUtils.unbind() + } + }) binding.rvFoodList.let { it.layoutManager = @@ -361,7 +376,7 @@ class CollectFragment : BaseFragment() { private fun searchByFoodName(name: String, block: (String) -> Unit) {} private fun hideWaitingDialog() { - settingActivity.dismissLoading() + currentActivity.dismissLoading() } private fun showWaitingDialog(msg: String) { @@ -369,6 +384,30 @@ class CollectFragment : BaseFragment() { Loading.updateContent(msg) return } - settingActivity.showLoading(msg) + currentActivity.showLoading(msg) } + + private lateinit var previewView: PreviewView + + private val cameraUtils: CameraUtils by lazy { + CameraUtils(requireActivity()) + } + + /** + * 初始化相机 + * @param container 相机预览容器 + */ + fun initCamera(container: ViewGroup) { + cameraUtils.initCamera() + val previewBinding = + LayoutCameraPreviewBinding.inflate(layoutInflater, container) + previewView = previewBinding.previewView.also { + it.updateLayoutParams { + width = 456.dp + height = 342.dp + } + } + cameraUtils.setPreviewController(previewView) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/DeviceConfigFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/DeviceConfigFragment.kt index 694b6ee..e0160bb 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/DeviceConfigFragment.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/DeviceConfigFragment.kt @@ -1,46 +1,22 @@ package com.shuwei.dish.match.ui.fragment import android.graphics.Typeface -import android.os.Bundle import android.text.SpannableStringBuilder import android.text.style.AbsoluteSizeSpan import android.text.style.ForegroundColorSpan import android.text.style.LineHeightSpan import android.text.style.StyleSpan -import android.util.Log -import android.util.SparseArray import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.FrameLayout import androidx.core.graphics.toColorInt -import androidx.core.view.forEach -import androidx.lifecycle.ViewModelProvider -import com.shuwei.dish.match.base.BaseApp import com.shuwei.dish.match.base.BaseFragment import com.shuwei.dish.match.databinding.FragmentDeviceConfigBinding -import com.shuwei.dish.match.db.AppRepository -import com.shuwei.dish.match.dialog.SeasoningSearchDialog -import com.shuwei.dish.match.entity.SeasoningEntity -import com.shuwei.dish.match.entity.ResetReasoningRecord -import com.shuwei.dish.match.adapter.TextCellAdapter -import com.shuwei.dish.match.base.BaseActivity -import com.shuwei.dish.match.utils.AddressUtil -import com.shuwei.dish.match.utils.JsonAssetsLoader -import com.shuwei.dish.match.utils.MultiClickDetector -import com.shuwei.dish.match.utils.WeightUtil -import com.shuwei.dish.match.utils.ext.appendText -import com.shuwei.dish.match.utils.ext.buildSpannableString -import com.shuwei.dish.match.utils.ext.dp -import com.shuwei.dish.match.utils.ext.clickWithDebounce -import com.shuwei.dish.match.utils.ext.gone -import com.shuwei.dish.match.utils.ext.toast -import com.shuwei.dish.match.utils.ext.visible -import com.shuwei.dish.match.viewmodel.AppViewModel -import com.shuwei.dish.match.viewmodel.factory.AppFactory import com.shuwei.dish.match.ui.SamplingListActivity import com.shuwei.dish.match.ui.SelectDishActivity import com.shuwei.dish.match.utils.SpTool +import com.shuwei.dish.match.utils.ext.appendText +import com.shuwei.dish.match.utils.ext.buildSpannableString +import com.shuwei.dish.match.utils.ext.dp import com.shuwei.dish.match.utils.ext.startActivity /** @@ -65,10 +41,10 @@ class DeviceConfigFragment : BaseFragment() { // private lateinit var appViewModel: AppViewModel - private val weightArray = SparseArray() - private val addressArray = AddressUtil.getWeighAddressArray() - private var seasoningItems = mutableListOf() - private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800) +// private val weightArray = SparseArray() +// private val addressArray = AddressUtil.getWeighAddressArray() +// private var seasoningItems = mutableListOf() +// private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800) override fun inflateBinding( inflater: LayoutInflater, @@ -77,7 +53,7 @@ class DeviceConfigFragment : BaseFragment() { return FragmentDeviceConfigBinding.inflate(inflater, container, false) } - override fun initialize(){ + override fun initialize() { initViewModel() initUI() // addWeighListener() @@ -140,7 +116,8 @@ class DeviceConfigFragment : BaseFragment() { loadCookSpan() loadSamplingSpan(isClicked = true) activity?.startActivity { - putExtra(SamplingListActivity.IS_CONFIG_PAGE, true) } + putExtra(SamplingListActivity.IS_CONFIG_PAGE, true) + } activity?.finish() } } 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 3fdb146..434dc4e 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 @@ -19,12 +19,13 @@ import com.shuwei.dish.match.base.DeviceRole import com.shuwei.dish.match.base.GlobalData import com.shuwei.dish.match.databinding.FragmentSeasoningConfigBinding import com.shuwei.dish.match.dialog.SeasoningSelectDialog +import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.SeasoningSlotEntity import com.shuwei.dish.match.scale.ScaleDeviceConfig import com.shuwei.dish.match.scale.ScaleEvent import com.shuwei.dish.match.scale.ScaleServiceManager import com.shuwei.dish.match.scale.ScaleEvent.SlotConfig -import com.shuwei.dish.match.ui.SettingActivity +import com.shuwei.dish.match.ui.SingleFragmentActivity import com.shuwei.dish.match.utils.SizeTool import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.ext.dp @@ -36,8 +37,10 @@ class SeasoningConfigFragment : BaseFragment() { companion object { private const val TAG = "SeasoningConfigFragment" + /** 重量增加阈值(克),超过此值才触发高亮 */ private const val WEIGHT_DELTA_THRESHOLD = 10.0 + /** 高亮自动恢复时间(毫秒) */ private const val HIGHLIGHT_DURATION_MS = 15_000L } @@ -47,21 +50,28 @@ class SeasoningConfigFragment : BaseFragment() { container: ViewGroup? ) = FragmentSeasoningConfigBinding.inflate(inflater, container, false) - private lateinit var settingActivity: SettingActivity + private lateinit var currentActivity: SingleFragmentActivity // private lateinit var appViewModel: AppViewModel private val adapter22 by lazy { buildAdapter22() } - private val adapter18 by lazy { Seasoning18GridAdapter(showNameOnly = true, leftRightSpace = 20.dp) } + private val adapter18 by lazy { + Seasoning18GridAdapter( + showNameOnly = true, + leftRightSpace = 20.dp + ) + } /** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */ private val weightSnapshot = mutableMapOf() + /** 主线程 Handler,用于延迟清除高亮 */ private val mainHandler = Handler(Looper.getMainLooper()) + /** 当前高亮清除任务,新高亮触发时取消旧任务 */ private var clearHighlightRunnable: Runnable? = null override fun initialize() { - settingActivity = activity as SettingActivity + currentActivity = activity as SingleFragmentActivity // initViewModel() setupRecyclerViews() bindAdapterClicks() @@ -73,62 +83,67 @@ class SeasoningConfigFragment : BaseFragment() { /** 绑定油盆格子点击,弹出调料选择弹窗并保存到 DEVICE_ID_1 */ private fun bindOilSlotClick() { binding.tvOilSlot.setOnClickListener { - SeasoningSelectDialog( - activity = settingActivity, - clickIndex = 0, - onItemSelected = { item -> - binding.tvOilSlot.text = item.goodsName ?: "-" - saveSlotAndBroadcast( - SeasoningSlotEntity( - deviceId = ScaleDeviceConfig.DEVICE_ID_1, - address = 1, - goodsId = item.goodsId, - goodsName = item.goodsName ?: "" - ) + openSeasoningSelectDialog(0) { item -> + binding.tvOilSlot.text = item.goodsName ?: "-" + saveSlotAndBroadcast( + SeasoningSlotEntity( + deviceId = ScaleDeviceConfig.DEVICE_ID_1, + address = 1, + goodsId = item.goodsId, + goodsName = item.goodsName ?: "" ) - } - ).show() + ) + } } } /** 绑定两个 Adapter 的格子点击,弹出调料选择弹窗 */ private fun bindAdapterClicks() { adapter22.onItemClick = { scaleData, position -> - SeasoningSelectDialog( - activity = settingActivity, - clickIndex = position, - onItemSelected = { item -> - adapter22.updateItemName(position, item.goodsName ?: "") - saveSlotAndBroadcast( - SeasoningSlotEntity( - deviceId = ScaleDeviceConfig.DEVICE_ID_22, - address = scaleData.address, - goodsId = item.goodsId, - goodsName = item.goodsName ?: "" - ) + openSeasoningSelectDialog(position) { item -> + adapter22.updateItemName(position, item.goodsName ?: "") + saveSlotAndBroadcast( + SeasoningSlotEntity( + deviceId = ScaleDeviceConfig.DEVICE_ID_22, + address = scaleData.address, + goodsId = item.goodsId, + goodsName = item.goodsName ?: "" ) - } - ).show() + ) + } } adapter18.onItemClick = { scaleData, position -> - SeasoningSelectDialog( - activity = settingActivity, - clickIndex = position, - onItemSelected = { item -> - adapter18.updateItemName(position, item.goodsName ?: "") - saveSlotAndBroadcast( - SeasoningSlotEntity( - deviceId = ScaleDeviceConfig.DEVICE_ID_18, - address = scaleData.address, - goodsId = item.goodsId, - goodsName = item.goodsName ?: "" - ) + openSeasoningSelectDialog(position) { item -> + adapter18.updateItemName(position, item.goodsName ?: "") + saveSlotAndBroadcast( + SeasoningSlotEntity( + deviceId = ScaleDeviceConfig.DEVICE_ID_18, + address = scaleData.address, + goodsId = item.goodsId, + goodsName = item.goodsName ?: "" ) - } - ).show() + ) + } } } + /** + * 打开调料选择弹窗 + * + * @param position 格子位置 + * @param callback 调料选择回调 + */ + private fun openSeasoningSelectDialog( + position: Int, + callback: (item: SeasoningEntity) -> Unit + ) { + SeasoningSelectDialog( + activity = currentActivity, + clickIndex = position, + onItemSelected = callback + ).show() + } + /** * 将单个槽位写入 Room,再读取全量配置广播给子设备 * 仅主设备执行广播,子设备不调用此方法 @@ -153,6 +168,7 @@ class SeasoningConfigFragment : BaseFragment() { private val size by lazy { SizeTool.getFlexLayoutSize(20.dp) } + /** 构建上层(22格)Adapter,需要先计算格子尺寸 */ private fun buildAdapter22(): Seasoning22GridAdapter { return Seasoning22GridAdapter( @@ -205,7 +221,8 @@ class SeasoningConfigFragment : BaseFragment() { } // 加载油盆格子名称(address=1) val oilSlot = slotsOil.firstOrNull { it.address == 1 } - binding.tvOilSlot.text = if (oilSlot != null && oilSlot.goodsName.isNotEmpty()) oilSlot.goodsName else "-" + binding.tvOilSlot.text = + if (oilSlot != null && oilSlot.goodsName.isNotEmpty()) oilSlot.goodsName else "-" } } } @@ -223,7 +240,10 @@ class SeasoningConfigFragment : BaseFragment() { * - STATE_STABLE:无条件更新基准(覆盖取走调料/归零等场景) */ private fun addWeightListener() { - Log.d(TAG, "addWeightListener: 注册监听, deviceId=${GlobalData.deviceId}, role=${GlobalData.deviceRole}") + Log.d( + TAG, + "addWeightListener: 注册监听, deviceId=${GlobalData.deviceId}, role=${GlobalData.deviceRole}" + ) if (GlobalData.deviceRole == DeviceRole.MASTER) { // 主设备:通过 allScales StateFlow 观测所有秤(含远端子设备秤) @@ -243,14 +263,21 @@ class SeasoningConfigFragment : BaseFragment() { return@forEach } val delta = data.weight - baseline - Log.d(TAG, "allScales: key=$key address=${data.address} state=${data.state} weight=${data.weight} baseline=$baseline delta=$delta") + Log.d( + TAG, + "allScales: key=$key address=${data.address} state=${data.state} weight=${data.weight} baseline=$baseline delta=$delta" + ) when { // 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发 data.state == WeightUtil.STATE_STABLE && delta > WEIGHT_DELTA_THRESHOLD -> { weightSnapshot[snapshotKey] = data.weight - Log.d(TAG, "allScales: 触发高亮 key=$key address=${data.address} delta=$delta") + Log.d( + TAG, + "allScales: 触发高亮 key=$key address=${data.address} delta=$delta" + ) triggerHighlight(data.deviceId, data.address, delta) } + data.state == WeightUtil.STATE_STABLE -> { weightSnapshot[snapshotKey] = data.weight } @@ -263,7 +290,10 @@ class SeasoningConfigFragment : BaseFragment() { WeightUtil.addWeightListener(TAG) { address, state, weight -> val snapshotKey = "${GlobalData.deviceId}#$address" val baseline = weightSnapshot[snapshotKey] - Log.d(TAG, "onWeight: address=$address state=$state weight=$weight baseline=$baseline") + Log.d( + TAG, + "onWeight: address=$address state=$state weight=$weight baseline=$baseline" + ) if (baseline == null) { weightSnapshot[snapshotKey] = weight @@ -271,7 +301,10 @@ class SeasoningConfigFragment : BaseFragment() { } val delta = weight - baseline - Log.d(TAG, "onWeight: address=$address state=$state weight=$weight baseline=$baseline delta=$delta") + Log.d( + TAG, + "onWeight: address=$address state=$state weight=$weight baseline=$baseline delta=$delta" + ) when { // 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发 @@ -280,6 +313,7 @@ class SeasoningConfigFragment : BaseFragment() { Log.d(TAG, "onWeight: 触发高亮 address=$address delta=$delta") triggerHighlight(GlobalData.deviceId, address, delta) } + state == WeightUtil.STATE_STABLE -> { weightSnapshot[snapshotKey] = weight } @@ -302,7 +336,10 @@ class SeasoningConfigFragment : BaseFragment() { val pos18 = if (sourceDeviceId == ScaleDeviceConfig.DEVICE_ID_18) ScaleDeviceConfig.SCALE_ORDER_18.indexOf(address) else -1 - Log.d(TAG, "triggerHighlight: sourceDeviceId=$sourceDeviceId address=$address pos22=$pos22 pos18=$pos18") + Log.d( + TAG, + "triggerHighlight: sourceDeviceId=$sourceDeviceId address=$address pos22=$pos22 pos18=$pos18" + ) // 两个列表都不包含该地址,忽略 if (pos22 < 0 && pos18 < 0) { @@ -318,6 +355,7 @@ class SeasoningConfigFragment : BaseFragment() { adapter22.highlightPosition(pos22) adapter18.clearHighlight() } + else -> { adapter18.highlightPosition(pos18) adapter22.clearHighlight() diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_right2.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_right2.png new file mode 100644 index 0000000000000000000000000000000000000000..15be3cfc1c4de34658ee560b977d627c0dba0e31 GIT binary patch literal 4758 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 jZtGAIc)`CfC0v|;k1cE*7Xx(7xef|Fc!dAPf literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index 82faa61..37d2d0b 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -1,77 +1,165 @@ - + android:gravity="center_vertical" + android:layout_marginHorizontal="32dp" + android:background="@drawable/shape_scale_cell"> - + android:layout_marginStart="32dp" + android:textColor="@color/black333" /> - - - - - - - - - - - - - - + android:layout_marginStart="32dp" + android:textColor="@color/black999" /> + - - + android:layout_height="120dp" + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginHorizontal="32dp" + android:layout_marginTop="32dp" + android:background="@drawable/shape_scale_cell"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +