style(ui): 优化食物识别界面布局和对话框标题
- 将食物照片区域包装在 CardView 中并调整样式 - 为食材列表容器添加滚动指示条功能 - 替换 RecyclerView 的滚动条为自定义指示条 - 更新多个对话框的标题文本以提高一致性 - 在准备烹饪界面添加重量显示文本 - 优化适配器数据更新和列表滚动逻辑 - 防止 StateFlow 重放导致的重复数据加载 - 添加新的滚动条绘制资源文件
This commit is contained in:
@@ -65,7 +65,7 @@ class CollectedFoodActivity : BaseActivity() {
|
||||
appendText(" 删除后无法恢复,${separator}确认要删除吗?")
|
||||
}
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setTitle("删除提示")
|
||||
.setContent(content)
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("确认") {
|
||||
|
||||
@@ -117,8 +117,8 @@ class DishSamplingActivity : BaseActivity() {
|
||||
|
||||
private fun saveDataRemindDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setContent("您好,当前页面存在未保存的数据,确认返回吗?")
|
||||
.setTitle("返回提示")
|
||||
.setContent("您好,当前页面存在未保存的数据,\n确认返回吗?")
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("确认") {
|
||||
if (pageFrom == HOME) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.os.Bundle
|
||||
import androidx.activity.addCallback
|
||||
import androidx.core.content.IntentCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter
|
||||
import com.shuwei.dish.match.base.BaseActivity
|
||||
import com.shuwei.dish.match.databinding.ActivityFoodRecognizeBinding
|
||||
@@ -93,6 +94,15 @@ class FoodRecognizeActivity : BaseActivity() {
|
||||
/** 当前待延迟更新的目标重量,避免相同重量重复重置计时器 */
|
||||
private var pendingWeight = 0.0
|
||||
|
||||
/** 右侧自定义滚动指示条最小高度 */
|
||||
private val scrollIndicatorMinHeightPx by lazy { (24 * resources.displayMetrics.density).toInt() }
|
||||
|
||||
private val scrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
updateScrollIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
private val adapter = GoodsInfoSearchAdapter(list).apply {
|
||||
setOnItemClickListener { _, _, position ->
|
||||
list.forEachIndexed { i, item -> item.isClicked = (i == position) }
|
||||
@@ -166,9 +176,13 @@ class FoodRecognizeActivity : BaseActivity() {
|
||||
* 初始化 RecyclerView
|
||||
*/
|
||||
private fun initRecyclerView() {
|
||||
binding.recyclerView.run {
|
||||
layoutManager = GridLayoutManager(this@FoodRecognizeActivity, 2)
|
||||
adapter = this@FoodRecognizeActivity.adapter
|
||||
binding.recyclerView.let {
|
||||
it.layoutManager = GridLayoutManager(this@FoodRecognizeActivity, 2)
|
||||
it.adapter = adapter
|
||||
it.isVerticalScrollBarEnabled = false
|
||||
it.removeOnScrollListener(scrollListener)
|
||||
it.addOnScrollListener(scrollListener)
|
||||
it.post { updateScrollIndicator() }
|
||||
}
|
||||
updateListVisibility()
|
||||
}
|
||||
@@ -178,12 +192,57 @@ class FoodRecognizeActivity : BaseActivity() {
|
||||
*/
|
||||
private fun updateListVisibility() {
|
||||
if (list.isEmpty()) {
|
||||
binding.recyclerView.gone()
|
||||
binding.flListContainer.gone()
|
||||
} else {
|
||||
binding.recyclerView.visible()
|
||||
binding.flListContainer.visible()
|
||||
binding.recyclerView.post { updateScrollIndicator() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 RecyclerView 滚动状态刷新右侧自定义指示条
|
||||
*/
|
||||
private fun updateScrollIndicator() {
|
||||
val recyclerView = binding.recyclerView
|
||||
val track = binding.vScrollIndicatorTrack
|
||||
val thumb = binding.vScrollIndicatorThumb
|
||||
|
||||
if (!recyclerView.canScrollVertically(1) && !recyclerView.canScrollVertically(-1)) {
|
||||
track.gone()
|
||||
thumb.gone()
|
||||
return
|
||||
}
|
||||
|
||||
val range = recyclerView.computeVerticalScrollRange()
|
||||
val extent = recyclerView.computeVerticalScrollExtent()
|
||||
val offset = recyclerView.computeVerticalScrollOffset()
|
||||
if (range <= 0 || extent <= 0 || range <= extent) {
|
||||
track.gone()
|
||||
thumb.gone()
|
||||
return
|
||||
}
|
||||
|
||||
val trackHeight = track.height.takeIf { it > 0 } ?: recyclerView.height
|
||||
if (trackHeight <= 0) return
|
||||
|
||||
val thumbHeight = ((extent.toFloat() / range) * trackHeight)
|
||||
.toInt()
|
||||
.coerceAtLeast(scrollIndicatorMinHeightPx)
|
||||
.coerceAtMost(trackHeight)
|
||||
|
||||
val maxTop = (trackHeight - thumbHeight).coerceAtLeast(0)
|
||||
val scrollable = (range - extent).coerceAtLeast(1)
|
||||
val thumbTop = ((offset.toFloat() / scrollable) * maxTop).toInt().coerceIn(0, maxTop)
|
||||
|
||||
if (thumb.layoutParams.height != thumbHeight) {
|
||||
thumb.layoutParams = thumb.layoutParams.apply { height = thumbHeight }
|
||||
}
|
||||
thumb.translationY = thumbTop.toFloat()
|
||||
|
||||
track.visible()
|
||||
thumb.visible()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化按钮点击事件
|
||||
*/
|
||||
@@ -219,6 +278,7 @@ class FoodRecognizeActivity : BaseActivity() {
|
||||
adapter.notifyDataSetChanged()
|
||||
binding.tvSelectedFood.text = item.goodsName ?: "-"
|
||||
updateListVisibility()
|
||||
binding.recyclerView.post { updateScrollIndicator() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -122,11 +122,18 @@ class PrepareCookActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun addViewClickListener() {
|
||||
binding.tvShowWeight.clickWithDebounce { WeightUtil.tareTwo(AddressUtil.ONE) }
|
||||
WeightUtil.addWeightListener(
|
||||
weightKey = TAG,
|
||||
getWeight = { address, state, weight ->
|
||||
if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) {
|
||||
runOnUiThread {
|
||||
binding.tvShowWeight.run {
|
||||
if (tag != weight) {
|
||||
text = "称重:${weight}g"
|
||||
tag = weight
|
||||
}
|
||||
}
|
||||
recognizeFood(weight)
|
||||
}
|
||||
}
|
||||
@@ -222,13 +229,12 @@ class PrepareCookActivity : BaseActivity() {
|
||||
existing.isSetFinished = true
|
||||
dishPartAdapter.notifyItemChanged(list.indexOf(existing))
|
||||
} else {
|
||||
list.add(entity.also {
|
||||
dishPartAdapter.add(entity.also {
|
||||
it.isNewDishType = true
|
||||
it.isSetFinished = true
|
||||
})
|
||||
val position = list.size - 1
|
||||
dishPartAdapter.notifyItemInserted(position)
|
||||
binding.rvDishPartList.smoothScrollToPosition(position)
|
||||
|
||||
binding.rvDishPartList.smoothScrollToPosition(list.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,11 +286,14 @@ class PrepareCookActivity : BaseActivity() {
|
||||
netViewModel.foodDetailState.collect { state ->
|
||||
when (state) {
|
||||
is UiState.Success -> {
|
||||
// 防止 StateFlow 重放导致 list 被重复清空
|
||||
if (isDetailLoaded) return@collect
|
||||
val detail = state.data
|
||||
if (detail == null) {
|
||||
toast("查询菜品信息为空")
|
||||
return@collect
|
||||
}
|
||||
isDetailLoaded = true
|
||||
loadDishDetail(detail)
|
||||
}
|
||||
|
||||
@@ -336,6 +345,7 @@ class PrepareCookActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private var firstReqSize = 0
|
||||
private var isDetailLoaded = false
|
||||
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||
private val dishPartAdapter by lazy {
|
||||
DishPartAdapter(list = list).apply {
|
||||
@@ -438,8 +448,8 @@ class PrepareCookActivity : BaseActivity() {
|
||||
*/
|
||||
private fun saveDataRemindDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setContent("您好,当前页面存在未保存的数据,确认返回吗?")
|
||||
.setTitle("返回提示")
|
||||
.setContent("您好,当前页面存在未保存的数据,\n确认返回吗?")
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("确认") {
|
||||
if (SpTool.cookMode == 1 && pageFrom == HOME) {
|
||||
|
||||
@@ -369,7 +369,7 @@ class SamplingListActivity : BaseActivity() {
|
||||
|
||||
private fun showDeviceConfigDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setTitle("配置提示")
|
||||
.setContent("请先在设备配置页面进行调料设置")
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("去设置") { startActivity<SettingActivity>() }
|
||||
|
||||
@@ -84,7 +84,7 @@ class SelectDishActivity : BaseActivity() {
|
||||
|
||||
private fun showDeviceConfigDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setTitle("配置提示")
|
||||
.setContent("请先在设备配置页面进行调料设置")
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("去设置") { startActivity<SettingActivity>() }
|
||||
|
||||
@@ -115,7 +115,7 @@ class SettingActivity : BaseActivity() {
|
||||
|
||||
private fun showNotGrantedCameraPermissionDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setTitle("权限提示")
|
||||
.setContent("暂无相机权限,无法使用食材采集功能,请确认是否同意开始权限?")
|
||||
.setNegativeButton("不同意")
|
||||
.setPositiveButton("同意") {
|
||||
|
||||
@@ -423,8 +423,8 @@ class SubmitFoodActivity : BaseActivity() {
|
||||
*/
|
||||
private fun remindSaveDataDialog() {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setContent("请确认是否存在未保存的数据?")
|
||||
.setTitle("保存提示")
|
||||
.setContent("可能存在未保存的数据,请确认?")
|
||||
.setNegativeButton("取消,留在页面")
|
||||
.setNeutralButton("返回上页,不保存") { finish() }
|
||||
.setPositiveButton("保存为烹饪中菜品") { cook() }
|
||||
@@ -436,7 +436,7 @@ class SubmitFoodActivity : BaseActivity() {
|
||||
*/
|
||||
private fun showRemindDialog(content: CharSequence, action: () -> Unit) {
|
||||
CommonDialog(this)
|
||||
.setTitle("温馨提示")
|
||||
.setTitle(food?.foodName ?: "温馨提示")
|
||||
.setContent(content)
|
||||
.setNegativeButton("取消")
|
||||
.setPositiveButton("确认") { action() }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:width="6dp" />
|
||||
<!-- <solid android:color="#66C4C4C4" />-->
|
||||
<solid android:color="@color/dish_green" />
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:width="10dp" />
|
||||
<solid android:color="#33000000" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
@@ -8,83 +8,115 @@
|
||||
android:padding="16dp"
|
||||
tools:background="@color/white">
|
||||
|
||||
<!-- 食材照片,权重占满剩余空间 -->
|
||||
<!-- 食材照片,权重占满剩余空间 -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
app:cardBackgroundColor="@color/white"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFoodPhoto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@color/bg_color" />
|
||||
tools:src="@mipmap/ic_launcher" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 识别到的食材列表,无数据时隐藏 -->
|
||||
<FrameLayout
|
||||
android:id="@+id/flListContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="260dp"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<!-- 识别到的食材列表,无数据时隐藏 -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:maxHeight="200dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:layout_height="match_parent"
|
||||
android:overScrollMode="never"
|
||||
android:visibility="gone"
|
||||
android:paddingEnd="6dp"
|
||||
android:paddingStart="0dp"
|
||||
android:clipToPadding="false"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
app:spanCount="2"
|
||||
tools:itemCount="4"
|
||||
tools:listitem="@layout/list_item_search_goods_info"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<!-- 选中的食材名称 -->
|
||||
<TextView
|
||||
android:id="@+id/tvSelectedFood"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:text="-"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp" />
|
||||
<View
|
||||
android:id="@+id/vScrollIndicatorTrack"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end|top"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:background="@drawable/scrollbar_track_food_recognize"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 秤1重量 -->
|
||||
<TextView
|
||||
android:id="@+id/tvWeight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/shape_white_12_corners"
|
||||
android:gravity="center"
|
||||
android:text="0.0 g"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp" />
|
||||
<View
|
||||
android:id="@+id/vScrollIndicatorThumb"
|
||||
android:layout_width="6dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="end|top"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:background="@drawable/scrollbar_thumb_food_recognize"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
<!-- 更换食材 -->
|
||||
<TextView
|
||||
android:id="@+id/btnChangeFood"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/shape_green_bg"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:text="更换食材"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
<!-- 选中的食材名称 -->
|
||||
<TextView
|
||||
android:id="@+id/tvSelectedFood"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center"
|
||||
android:text="-"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<!-- 取消 -->
|
||||
<TextView
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/shape_white_12_corners"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:text="取消"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
<!-- 秤1重量 -->
|
||||
<TextView
|
||||
android:id="@+id/tvWeight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/shape_white_12_corners"
|
||||
android:gravity="center"
|
||||
android:text="0.0 g"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp" />
|
||||
|
||||
<!-- 更换食材 -->
|
||||
<TextView
|
||||
android:id="@+id/btnChangeFood"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:background="@drawable/shape_green_bg"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="更换食材"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- 取消 -->
|
||||
<TextView
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="90dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:background="@drawable/shape_white_12_corners"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:text="取消"
|
||||
android:textColor="@color/black333"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -75,6 +75,16 @@
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvShowWeight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:padding="10dp"
|
||||
tools:text="0g"
|
||||
android:textColor="@color/black666"
|
||||
android:textSize="28sp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/flCameraContainer"
|
||||
android:layout_width="1dp"
|
||||
|
||||
Reference in New Issue
Block a user