From 617ccfb456d95869077391b420ead10eacea20d0 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 24 Apr 2026 10:07:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(dialog):=20=E8=B0=83=E6=96=99=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=AF=B9=E8=AF=9D=E6=A1=86=E5=A2=9E=E5=8A=A0=E6=BB=91?= =?UTF-8?q?=E5=8A=A8=E5=86=B2=E7=AA=81=E5=A4=84=E7=90=86=E5=92=8C=E9=87=8D?= =?UTF-8?q?=E9=87=8F=E4=BC=A0=E9=80=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 dialog_seasoning_select.xml 布局高度为 match_parent 并添加标题文本 - 调整 SmartRefreshLayout 高度限制并移除 RecyclerView 内边距 - 在 FoodRecognizeActivity 中新增 currentWeight 参数传递机制 - 移除 WeightUtil 监听器相关代码并初始化当前重量值 - 在 PrepareCookActivity 中传递当前重量到识别页面 - 从 SeasoningConfigFragment 和 SeasoningSelectDialog 中移除无用参数 - 添加 Window.Callback 触摸事件拦截解决 RecyclerView 滑动冲突 - 实现触摸点位置检测动态控制 BottomSheet 拖拽行为 --- .../match/dialog/SeasoningSelectDialog.kt | 39 ++++++++---- .../dish/match/ui/FoodRecognizeActivity.kt | 63 ++++++++++--------- .../dish/match/ui/PrepareCookActivity.kt | 3 + .../ui/fragment/SeasoningConfigFragment.kt | 1 - .../res/layout/dialog_seasoning_select.xml | 19 ++++-- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/shuwei/dish/match/dialog/SeasoningSelectDialog.kt b/app/src/main/java/com/shuwei/dish/match/dialog/SeasoningSelectDialog.kt index a55443f..84a18d4 100644 --- a/app/src/main/java/com/shuwei/dish/match/dialog/SeasoningSelectDialog.kt +++ b/app/src/main/java/com/shuwei/dish/match/dialog/SeasoningSelectDialog.kt @@ -1,17 +1,18 @@ package com.shuwei.dish.match.dialog import android.annotation.SuppressLint +import android.graphics.Rect import android.os.Handler import android.os.Looper import android.view.Gravity import android.view.LayoutInflater +import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import android.view.Window import android.view.WindowManager -import androidx.core.view.isEmpty import androidx.core.widget.addTextChangedListener import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.google.android.material.bottomsheet.BottomSheetDialog import com.shuwei.dish.match.R import com.shuwei.dish.match.adapter.SeasoningSearchAdapter @@ -30,7 +31,6 @@ import com.shuwei.dish.match.utils.ext.toast */ class SeasoningSelectDialog( private val activity: BaseActivity, - private val clickIndex: Int, private val onItemSelected: (item: SeasoningEntity) -> Unit ) : BottomSheetDialog(activity, R.style.BottomSheet) { @@ -84,18 +84,10 @@ class SeasoningSelectDialog( addOnActionSearchListener { searchGoods(this) } } - // RecyclerView 初始化及滑动冲突处理 + // RecyclerView 初始化 binding.recyclerView.run { layoutManager = GridLayoutManager(activity, 3, GridLayoutManager.VERTICAL, false) adapter = this@SeasoningSelectDialog.adapter - addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) { - super.onScrolled(rv, dx, dy) - // 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突 - val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top - binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0) - } - }) } binding.refreshLayout.run { @@ -109,11 +101,32 @@ class SeasoningSelectDialog( binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) } } - /** 弹窗显示时自动加载默认调料列表 */ + /** 弹窗显示时自动加载默认调料列表,并在 Window.Callback 层提前拦截触摸以解决滑动冲突 */ override fun show() { super.show() pageNo = 1 getGoodsList() + // Window.Callback.dispatchTouchEvent 在整个 View 树的 onInterceptTouchEvent 之前执行, + // 是最早能感知触摸的时机。在此处判断触摸点位置来控制 behavior.isDraggable, + // 从而确保 BottomSheetBehavior 在 CoordinatorLayout.onInterceptTouchEvent 时 + // 已经是禁用状态,不会拦截列表区域的滑动手势。 + val originalCallback = window?.callback ?: return + window?.callback = object : Window.Callback by originalCallback { + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + when (event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + val rect = Rect() + binding.refreshLayout.getGlobalVisibleRect(rect) + // 触摸点落在列表区域内则禁止 BottomSheet 拖拽 + behavior.isDraggable = !rect.contains(event.rawX.toInt(), event.rawY.toInt()) + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + behavior.isDraggable = true + } + } + return originalCallback.dispatchTouchEvent(event) + } + } } /** diff --git a/app/src/main/java/com/shuwei/dish/match/ui/FoodRecognizeActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/FoodRecognizeActivity.kt index f8278c6..63e7c0d 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/FoodRecognizeActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/FoodRecognizeActivity.kt @@ -12,7 +12,6 @@ import com.shuwei.dish.match.databinding.ActivityFoodRecognizeBinding import com.shuwei.dish.match.dialog.FoodSearchDialog import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.utils.ActivityManager -import com.shuwei.dish.match.utils.AddressUtil import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.ext.clickWithDebounce import com.shuwei.dish.match.utils.ext.gone @@ -28,6 +27,7 @@ class FoodRecognizeActivity : BaseActivity() { companion object { private const val TAG = "FoodRecognizeActivity" private const val EXTRA_IMAGE_URI = "extra_image_uri" + private const val EXTRA_CURRENT_WEIGHT = "extra_current_weight" const val EXTRA_SELECTED_ITEM = "extra_selected_item" const val IS_MANUAL_CANCEL = "isManualCancel" @@ -44,12 +44,14 @@ class FoodRecognizeActivity : BaseActivity() { fun start( activity: BaseActivity, imageUri: String? = null, + currentWeight: Double = 0.0, goodsList: ArrayList = arrayListOf(), finishCallback: (Boolean, CookFoodGoodsEntity?) -> Unit = { _, _ -> } ) { pendingGoodsList = goodsList val launchIntent = Intent(activity, FoodRecognizeActivity::class.java).apply { putExtra(EXTRA_IMAGE_URI, imageUri) + putExtra(EXTRA_CURRENT_WEIGHT, currentWeight) } activity.startActivity(launchIntent) { resultIntent -> val isManualCancel = resultIntent?.getBooleanExtra(IS_MANUAL_CANCEL, false) ?: false @@ -145,6 +147,8 @@ class FoodRecognizeActivity : BaseActivity() { if (!imageUri.isNullOrBlank()) { binding.ivFoodPhoto.setImageURI(imageUri.toUri()) } + currentWeight = intent.getDoubleExtra(EXTRA_CURRENT_WEIGHT, 0.0) + binding.tvWeight.text = "${currentWeight}g" // 取出内存缓存的食材列表,取用后立即清空 val goodsList = pendingGoodsList?.also { pendingGoodsList = null } @@ -153,6 +157,7 @@ class FoodRecognizeActivity : BaseActivity() { // 默认选中第一项 selectedPosition = 0 list[0].isClicked = true + list[0].useWeight = currentWeight binding.tvSelectedFood.text = list[0].goodsName ?: "-" } } @@ -222,40 +227,40 @@ class FoodRecognizeActivity : BaseActivity() { * 低于阈值说明食材已被取走,保留上次有效值等待页面关闭 */ private fun registerWeightListener() { - WeightUtil.addWeightListener(TAG) { address, state, weight -> - if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) { - runOnUiThread { - currentWeight = weight - binding.tvWeight.run { - if (tag != weight) { - text = "$weight g" - tag = weight - } - } - if (weight >= PrepareCookActivity.WEIGHT_RECOGNIZE_VALUE) { - adapter.items.firstOrNull { it.isClicked }?.let { item -> - if (pendingWeight != weight) { - // 无论增减,均延迟更新,避免手拿物品时的瞬时增重干扰 - cancelPendingWeightUpdate() - pendingWeight = weight - pendingWeightRunnable = Runnable { - item.useWeight = weight - pendingWeightRunnable = null - }.also { handler.postDelayed(it, 3000) } - } - } - } - } - } - } +// WeightUtil.addWeightListener(TAG) { address, state, weight -> +// if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) { +// runOnUiThread { +// currentWeight = weight +// binding.tvWeight.run { +// if (tag != weight) { +// text = "$weight g" +// tag = weight +// } +// } +// if (weight >= PrepareCookActivity.WEIGHT_RECOGNIZE_VALUE) { +// adapter.items.firstOrNull { it.isClicked }?.let { item -> +// if (pendingWeight != weight) { +// // 无论增减,均延迟更新,避免手拿物品时的瞬时增重干扰 +// cancelPendingWeightUpdate() +// pendingWeight = weight +// pendingWeightRunnable = Runnable { +// item.useWeight = weight +// pendingWeightRunnable = null +// }.also { handler.postDelayed(it, 3000) } +// } +// } +// } +// } +// } +// } } /** * 取消待执行的延迟重量更新任务 */ private fun cancelPendingWeightUpdate() { - pendingWeightRunnable?.let { handler.removeCallbacks(it) } - pendingWeightRunnable = null + // pendingWeightRunnable?.let { handler.removeCallbacks(it) } + // pendingWeightRunnable = null } /** diff --git a/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt index 08f67c7..0ed4e8d 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/PrepareCookActivity.kt @@ -196,6 +196,7 @@ class PrepareCookActivity : BaseActivity() { if (weight < WEIGHT_RECOGNIZE_VALUE) { showRecognizePage = false manualCancelFlag = false + lastWeight = weight FoodRecognizeActivity.close() return } @@ -515,9 +516,11 @@ class PrepareCookActivity : BaseActivity() { } ) } + lastWeight = currentWeight FoodRecognizeActivity.start( activity = this, imageUri = lastPhotoUri?.toString(), + currentWeight = currentWeight, goodsList = ArrayList(foodList), finishCallback = { isManualCancel, entity -> Log.d(TAG, "queryFood: isManualCancel=$isManualCancel, entity=${entity.toJsonString()}") 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 dc99585..9c8dec4 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 @@ -136,7 +136,6 @@ class SeasoningConfigFragment : BaseFragment() { ) { SeasoningSelectDialog( activity = currentActivity, - clickIndex = position, onItemSelected = callback ).show() } diff --git a/app/src/main/res/layout/dialog_seasoning_select.xml b/app/src/main/res/layout/dialog_seasoning_select.xml index 11b6669..7b3ed3a 100644 --- a/app/src/main/res/layout/dialog_seasoning_select.xml +++ b/app/src/main/res/layout/dialog_seasoning_select.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="match_parent" android:gravity="center_horizontal" tools:background="@color/white" android:orientation="vertical"> @@ -15,6 +15,16 @@ android:layout_marginTop="30dp" android:background="@drawable/shape_gray_dc_5" /> + +