refactor(ui): 重构主界面食物列表布局和支付模式切换功能

- 将原有的RecyclerView替换为FrameLayout容器,实现动态布局加载
- 新增layout_main_food_list.xml和layout_main_food_list2.xml两个布局文件
- 实现联合支付和独立支付两种模式下的不同UI展示
- 集成食物详情显示功能,通过include方式引入layout_eat_detail.xml
- 更新数据绑定逻辑,支持两种支付模式下的食物列表显示
- 迁移SharedPreferences操作至SpTool工具类统一管理
- 优化食物识别结果显示逻辑和搜索按钮状态控制
- 重构RecyclerView初始化和适配器设置代码结构
This commit is contained in:
2026-04-24 15:37:57 +08:00
parent e3b01ff789
commit 03c5aee785
8 changed files with 178 additions and 76 deletions
@@ -13,6 +13,7 @@ import android.text.TextUtils
import android.view.Display
import android.view.View
import android.view.ViewOutlineProvider
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
import androidx.camera.core.CameraSelector
@@ -22,13 +23,18 @@ import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.common.util.concurrent.ListenableFuture
import com.sw.dualscreen.GlobalData
import com.sw.dualscreen.GlobalKey
import com.sw.dualscreen.adapter.MainFoodListAdapter
import com.sw.dualscreen.databinding.ActivityMainBinding
import com.sw.dualscreen.databinding.LayoutEatDetailBinding
import com.sw.dualscreen.databinding.LayoutMainFoodList2Binding
import com.sw.dualscreen.databinding.LayoutMainFoodListBinding
import com.sw.dualscreen.dialog.EnvSwitchDialog
import com.sw.dualscreen.dialog.RemindDialog
import com.sw.dualscreen.ext.dp
@@ -180,6 +186,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
// SPUtil.getInstance().get(GlobalKey.KEY_SETTLEMENT_MODE, 1)
// }
private lateinit var rvFoodList: RecyclerView
private lateinit var tvToSearch: TextView
lateinit var layoutEatDetailBinding: LayoutEatDetailBinding
override fun getViewModel(): BaseViewModel {
return viewModel
}
@@ -202,25 +212,66 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
initData()
}
private fun initLayoutEatDetailBinding(mode: Int) {
binding.flFoodList.removeAllViews()
if (mode == 0) {
//联合支付
val b = LayoutMainFoodList2Binding.inflate(layoutInflater, binding.flFoodList, true)
rvFoodList = b.rvFoodList
tvToSearch = b.tvToSearch
layoutEatDetailBinding = b.detailInclude
layoutEatDetailBinding.llFoodTitle.gone()
// layoutEatDetailBinding.root.invisible()
} else {
//独立支付
val b = LayoutMainFoodListBinding.inflate(layoutInflater, binding.flFoodList, true)
rvFoodList = b.rvFoodList
tvToSearch = b.tvToSearch
layoutEatDetailBinding = b.detailInclude
layoutEatDetailBinding.llFoodTitle.gone()
layoutEatDetailBinding.root.gone()
}
tvToSearch.setOnClickListener {
bottomSheetDialog = CustomBottomSheetDialog.newInstance(viewModel) {
checkedItem = it
it.photoUri = null
adapter.items.forEachIndexed { index, info ->
adapter.items[index].isChecked = false
}
adapter.notifyDataSetChanged()
resetSelectedFood(it)
}
bottomSheetDialog!!.show(supportFragmentManager, "CustomBottomSheetDialog")
}
rvFoodList.let {
it.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)
it.adapter = adapter
}
}
private fun initData() {
startFaceTask()
}
private fun initView() {
initLayoutEatDetailBinding(SpTool.settlementMode)
viewModel.getDeviceConfig { deviceConfig ->
runOnUiThread {
if (deviceConfig == null) {
ToastUtils.showToast("获取设备配置数据失败")
initLayoutEatDetailBinding(SpTool.settlementMode)
return@runOnUiThread
}
//结算模式:1-独立支付,2-联合结算
settlementMode = if (deviceConfig.payType == 2) 0 else 1
SPUtil.getInstance().put(GlobalKey.KEY_SETTLEMENT_MODE, settlementMode)
SpTool.settlementMode = settlementMode
GlobalData.appId = deviceConfig.arcsoftAppId ?: ""
GlobalData.sdkKey = deviceConfig.arcsoftSdkKey ?: ""
GlobalData.activeKey = deviceConfig.arcsoftActiveKey ?: ""
viewModel.activeEngine()
initLayoutEatDetailBinding(settlementMode)
}
}
updateDateTime()
@@ -264,23 +315,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
}
binding.previewView.clipToOutline = true
binding.tvToSearch.setOnClickListener {
bottomSheetDialog = CustomBottomSheetDialog.newInstance(viewModel) {
checkedItem = it
it.photoUri = null
adapter.items.forEachIndexed { index, info ->
adapter.items[index].isChecked = false
}
adapter.notifyDataSetChanged()
resetSelectedFood(it)
}
bottomSheetDialog!!.show(supportFragmentManager, "CustomBottomSheetDialog")
}
binding.recyclerview.let {
it.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)
it.adapter = adapter
}
binding.tvFoodName.setOnClickListener {
SensorScaleUtils.zero()
}
@@ -545,7 +579,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
log("registerDataChange识别后查询接口数据:$queryData,识别数据:$recData")
if (list.isEmpty()) {
foodRecognizeState = false
binding.tvToSearch.let {
tvToSearch.let {
it.text = "未查询到,手动搜索"
it.visible()
}
@@ -571,7 +605,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
// }
adapter.submitList(list)
binding.recyclerview.visible()
rvFoodList.visible()
checkedItem = list[0].also {
it.photoUri = lastPhotoUri
@@ -582,10 +616,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
// lastPhotoUri = null
LightManager.closeRedLight()
binding.tvToSearch.let {
tvToSearch.let {
it.text = "以上都不是,手动搜索"
it.visible()
}
log("registerDataChange识别完成:visible=${rvFoodList.isVisible},count=${rvFoodList.childCount}")
}
private fun setupCamera() {
@@ -756,9 +791,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
@SuppressLint("NotifyDataSetChanged")
fun clearRecognizeFood() {
log("clearRecognizeFood")
binding.recyclerview.invisible()
rvFoodList.invisible()
layoutEatDetailBinding.root.invisible()
adapter.submitList(null)
binding.tvToSearch.gone()
tvToSearch.gone()
binding.previewView.visible()
binding.ivImg.gone()
@@ -1294,7 +1330,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
//binding.layoutRescan.visibility = View.VISIBLE
withContext(Dispatchers.Main) {
binding.tvToSearch.let {
tvToSearch.let {
it.text = "未识别到,手动搜索"
it.visible()
}
@@ -9,6 +9,7 @@ import com.sw.dualscreen.model.response.ChargeModeEvent
import com.sw.dualscreen.model.response.ResetRecognizeEvent
import com.sw.dualscreen.sdk.SensorScaleUtils
import com.sw.dualscreen.utils.SPUtil
import com.sw.dualscreen.utils.SpTool
import com.sw.plate.utils.ToastUtils
import org.greenrobot.eventbus.EventBus
import kotlin.math.roundToInt
@@ -23,8 +24,8 @@ class BusinessFragment: BaseFragment<FragmentBusinessBinding>() {
binding.rgSettlement.let {
//val settlementMode = if (binding.rgSettlement.checkedRadioButtonId == R.id.rbJointPayment) 0 else 1
val mode = SPUtil.getInstance().get(GlobalKey.KEY_SETTLEMENT_MODE, 1)
it.check(if (mode == 0) R.id.rbJointPayment else R.id.rbIndependentPayment)
//val mode = SPUtil.getInstance().get(GlobalKey.KEY_SETTLEMENT_MODE, 1)
it.check(if (SpTool.settlementMode == 0) R.id.rbJointPayment else R.id.rbIndependentPayment)
binding.rbJointPayment.isEnabled = false
binding.rbIndependentPayment.isEnabled = false
}
@@ -16,11 +16,11 @@ import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.postDelayed
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.arcsoft.face.ErrorInfo
import com.sw.dualscreen.BuildConfig
import com.sw.dualscreen.GlobalKey
@@ -64,7 +64,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import timber.log.Timber
import java.text.DecimalFormat
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.roundToInt
@@ -327,6 +326,7 @@ class MainScreenPresentation(
loadOrderList(userId) {
loadUserNutritionData(userId)
}
activity.layoutEatDetailBinding.root.visible()
} else {
//独立支付
loadUserNutritionData(userId)
@@ -776,10 +776,14 @@ class MainScreenPresentation(
val fruitsVegetables = energy.fruitsVegetables
val meatEggs = energy.meatEggs
binding.detailInclude.tvTotalCalorie.text = "总热量:${totalKcal.roundedDecimalPlace(1)}千卡"
val showTotalCalorie = "总热量:${totalKcal.roundedDecimalPlace(1)}千卡"
binding.detailInclude.tvTotalCalorie.text = showTotalCalorie
activity.layoutEatDetailBinding.tvTotalCalorie.text = showTotalCalorie
val totalWeight = (userNutrition?.eatWeightSum ?: 0.0) + weight
binding.detailInclude.tvTotalWeight.text = "总重量:${totalWeight.roundedDecimalPlace(1)}"
val showTotalWeight = "总重量:${totalWeight.roundedDecimalPlace(1)}"
binding.detailInclude.tvTotalWeight.text = showTotalWeight
activity.layoutEatDetailBinding.tvTotalWeight.text = showTotalWeight
val include = binding.nutritionInclude
@@ -1449,6 +1453,16 @@ class MainScreenPresentation(
FoodOrderAdapter(foodOrderList)
}
private fun initRv(rv: RecyclerView) {
rv.run {
if (adapter == null) {
layoutManager =
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
adapter = foodOrderAdapter
}
}
}
/**
* 加载订单列表
*/
@@ -1460,13 +1474,8 @@ class MainScreenPresentation(
it.root.updateLayoutParams {
height = activity.screenSize[1] / 2 + 120.dp
}
it.rvFoodList.run {
if (adapter == null) {
layoutManager =
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
adapter = foodOrderAdapter
}
}
initRv(it.rvFoodList)
initRv(activity.layoutEatDetailBinding.rvFoodList)
userViewModel.getFoodOrderList(userId) { model ->
activity.runOnUiThread {
if (model == null) return@runOnUiThread
@@ -17,13 +17,13 @@ object SpTool {
var lastFaceTimestamp: Long
get() = spUtil?.get(LAST_FACE_TIMESTAMP, 0L)?:0L
get() = spUtil?.get(LAST_FACE_TIMESTAMP, 0L) ?: 0L
set(timestamp) {
spUtil?.put(LAST_FACE_TIMESTAMP, timestamp)
}
var firstGetFace: Boolean
get() = spUtil?.get(IS_FIRST_GET_FACE, true)?:true
get() = spUtil?.get(IS_FIRST_GET_FACE, true) ?: true
set(value) {
spUtil?.boolean(IS_FIRST_GET_FACE, value)
}
@@ -33,5 +33,10 @@ object SpTool {
set(value) {
spUtil?.put(GlobalKey.KEY_BASE_URL, value)
}
var settlementMode: Int
get() = spUtil?.get(GlobalKey.KEY_SETTLEMENT_MODE, 0) ?: 0
set(value) {
spUtil?.put(GlobalKey.KEY_SETTLEMENT_MODE, value)
}
}
+4 -37
View File
@@ -92,51 +92,18 @@
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
<FrameLayout
android:id="@+id/flFoodList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="42dp"
android:layout_weight="1"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="8"
tools:listitem="@layout/list_item_search_food" />
<TextView
android:id="@+id/tvToSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:layout_marginBottom="0dp"
android:padding="10dp"
android:text="以上都不是,手动搜索"
android:textColor="#FFFF3232"
android:textSize="31sp"
android:textStyle="bold"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="54dp"
android:gravity="center">
<TextView
android:id="@+id/tvWeightRealInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="12sp"
tools:text="以上都不是,手动搜索" />
</LinearLayout>
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/flPay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:layout_marginTop="45dp"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatButton
@@ -8,6 +8,7 @@
tools:ignore="HardcodedText,UseCompatTextViewDrawableXml">
<FrameLayout
android:id="@+id/llFoodTitle"
android:layout_width="match_parent"
android:layout_height="80dp">
@@ -54,6 +55,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:overScrollMode="never"
tools:listitem="@layout/layout_food_list_header" />
<LinearLayout
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFoodList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="42dp"
android:layout_weight="1"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="8"
tools:listitem="@layout/list_item_search_food" />
<TextView
android:id="@+id/tvToSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:layout_gravity="center_horizontal"
android:padding="10dp"
tools:text="以上都不是,手动搜索"
android:textColor="#FFFF3232"
android:textSize="31sp"
android:textStyle="bold"/>
<include
android:id="@+id/detailInclude"
layout="@layout/layout_eat_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="14dp"
android:visibility="gone"/>
</LinearLayout>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFoodList"
android:layout_width="match_parent"
android:layout_height="264dp"
android:layout_marginHorizontal="14dp"
android:layout_marginTop="42dp"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:itemCount="8"
tools:listitem="@layout/list_item_search_food" />
<TextView
android:id="@+id/tvToSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:layout_gravity="center_horizontal"
android:padding="10dp"
tools:text="以上都不是,手动搜索"
android:textColor="#FFFF3232"
android:textSize="31sp"
android:textStyle="bold"/>
<include
android:id="@+id/detailInclude"
layout="@layout/layout_eat_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="14dp"/>
</LinearLayout>