feat(ui): 新增餐品列表和菜品包装页面
- 创建了 MealListActivity 餐品列表页面,用于展示可选的餐品 - 实现了餐品列表的 RecyclerView 展示和点击跳转功能 - 添加了 PackActivity 菜品包装页面,支持食材构成管理 - 集成了相机预览功能用于食材识别 - 实现了重量识别和食材添加功能 - 添加了侧滑删除菜单和食材重量管理 - 创建了 MealListAdapter 适配器用于餐品列表展示
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.shuwei.dish.match.databinding.ListItemFood2Binding
|
||||||
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 餐品列表适配器
|
||||||
|
*/
|
||||||
|
class MealListAdapter(list: MutableList<NutFoodOptionVO>) :
|
||||||
|
BaseQuickAdapter<NutFoodOptionVO, MealListAdapter.VH>(list) {
|
||||||
|
|
||||||
|
inner class VH(var binding: ListItemFood2Binding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: VH,
|
||||||
|
position: Int,
|
||||||
|
item: NutFoodOptionVO?
|
||||||
|
) {
|
||||||
|
holder.binding.tvDishInfo.text = item?.foodName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(
|
||||||
|
context: Context,
|
||||||
|
parent: ViewGroup,
|
||||||
|
viewType: Int
|
||||||
|
): VH {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val binding = ListItemFood2Binding.inflate(inflater, parent, false)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.shuwei.dish.match.adapter.MealListAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.databinding.ActivityMealListBinding
|
||||||
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 餐品列表页面
|
||||||
|
*/
|
||||||
|
class MealListActivity : BaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val MEAL_ITEM = "mealItem"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by lazy { ActivityMealListBinding.inflate(layoutInflater) }
|
||||||
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
|
|
||||||
|
private val mealList = mutableListOf<NutFoodOptionVO>()
|
||||||
|
private val mealAdapter by lazy { MealListAdapter(mealList) }
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
setTitleBar(titleBarAction = {
|
||||||
|
it.visible()
|
||||||
|
}, titleAction = {
|
||||||
|
it.text = "餐品列表"
|
||||||
|
}, rightIconAction = {
|
||||||
|
it.gone()
|
||||||
|
}, backAction = {
|
||||||
|
it.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
initRecyclerView()
|
||||||
|
loadMealList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 RecyclerView
|
||||||
|
*/
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.rvMealList.layoutManager = LinearLayoutManager(this)
|
||||||
|
binding.rvMealList.adapter = mealAdapter
|
||||||
|
mealAdapter.setOnItemClickListener { _, _, position ->
|
||||||
|
val item = mealList.getOrNull(position) ?: return@setOnItemClickListener
|
||||||
|
val intent = Intent(this, PackActivity::class.java).apply {
|
||||||
|
putExtra(PackActivity.MEAL_ITEM, item)
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载餐品列表
|
||||||
|
*/
|
||||||
|
private fun loadMealList() {
|
||||||
|
viewModelV2.getFoodOptionsWithCallback(
|
||||||
|
keyword = null,
|
||||||
|
pageNum = 1,
|
||||||
|
pageSize = 100,
|
||||||
|
onLoading = {
|
||||||
|
showLoading("加载中……")
|
||||||
|
},
|
||||||
|
onResult = { state ->
|
||||||
|
dismissLoading()
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val records = state.data?.records
|
||||||
|
if (records.isNullOrEmpty()) {
|
||||||
|
toast("暂无数据")
|
||||||
|
return@getFoodOptionsWithCallback
|
||||||
|
}
|
||||||
|
mealList.clear()
|
||||||
|
mealList.addAll(records)
|
||||||
|
mealAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
is UiState.Error -> {
|
||||||
|
toast(state.msg)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,607 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.activity.addCallback
|
||||||
|
import androidx.core.content.IntentCompat
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.adapter.FoodMaterialAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.databinding.ActivityPackBinding
|
||||||
|
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
||||||
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import com.shuwei.dish.match.objbox.FoodModule
|
||||||
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
|
import com.shuwei.dish.match.utils.CameraUtils
|
||||||
|
import com.shuwei.dish.match.utils.ImageUtil
|
||||||
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
|
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
||||||
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
|
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||||
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
import com.yanzhenjie.recyclerview.SwipeMenuItem
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.math.abs
|
||||||
|
import com.shuwei.dish.match.model.NutFoodComposition
|
||||||
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
class PackActivity : BaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "PackActivity"
|
||||||
|
const val MEAL_ITEM = "mealItem"
|
||||||
|
const val PAGE_FROM = "pageFrom"
|
||||||
|
const val HOME = "home"
|
||||||
|
const val WEIGHT_CHANGE_VALUE = 5
|
||||||
|
const val WEIGHT_RECOGNIZE_VALUE = 10
|
||||||
|
|
||||||
|
/** 主材数量上限 */
|
||||||
|
const val MATERIAL_COUNT = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binding by lazy { ActivityPackBinding.inflate(layoutInflater) }
|
||||||
|
|
||||||
|
private val cameraUtils: CameraUtils by lazy { CameraUtils(this) }
|
||||||
|
|
||||||
|
private var mealItem: NutFoodOptionVO? = null
|
||||||
|
|
||||||
|
/** 来源页面标识,HOME 时返回跳转 SamplingListActivity */
|
||||||
|
private var pageFrom: String? = null
|
||||||
|
|
||||||
|
private var goodsList: MutableList<CookFoodGoodsEntity>? = null
|
||||||
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
pageFrom = intent.getStringExtra(PAGE_FROM)
|
||||||
|
mealItem = IntentCompat.getParcelableExtra(intent, MEAL_ITEM, NutFoodOptionVO::class.java)
|
||||||
|
|
||||||
|
mealItem?.let {
|
||||||
|
binding.etInputDish.run {
|
||||||
|
setText(it.foodName)
|
||||||
|
tag = it.foodName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isSamplingMode = SpTool.cookMode == 1
|
||||||
|
val titleText = if (isSamplingMode) "菜品信息采集" else "菜品净菜包装"
|
||||||
|
setTitleBar(titleBarAction = {
|
||||||
|
it.visible()
|
||||||
|
}, titleAction = {
|
||||||
|
it.text = titleText
|
||||||
|
}, rightIconAction = {
|
||||||
|
it.gone()
|
||||||
|
}, backAction = {
|
||||||
|
it.setOnClickListener {
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 不可编辑,仅展示菜名
|
||||||
|
binding.etInputDish.isFocusable = false
|
||||||
|
binding.etInputDish.isFocusableInTouchMode = false
|
||||||
|
binding.ivDishSearch.gone()
|
||||||
|
|
||||||
|
addViewClickListener()
|
||||||
|
addBackKeyListener()
|
||||||
|
initCamera(binding.flCameraContainer)
|
||||||
|
initRecyclerView()
|
||||||
|
initObserver()
|
||||||
|
|
||||||
|
// 根据传入的餐品数据加载食材列表
|
||||||
|
mealItem?.let {
|
||||||
|
val compositions = it.compositions
|
||||||
|
if (!compositions.isNullOrEmpty()) {
|
||||||
|
loadDishCompositions(compositions)
|
||||||
|
} else {
|
||||||
|
toast("该餐品无食材构成信息")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var currentWeight = 0.0
|
||||||
|
private fun addViewClickListener() {
|
||||||
|
// ========== 重量识别相关功能已注释 ==========
|
||||||
|
WeightUtil.addWeightListener(
|
||||||
|
weightKey = TAG,
|
||||||
|
getWeight = { address, state, weight ->
|
||||||
|
if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) {
|
||||||
|
runOnUiThread {
|
||||||
|
currentWeight = weight - initialWeight
|
||||||
|
binding.tvShowWeight.run {
|
||||||
|
if (tag != currentWeight) {
|
||||||
|
// text = "称重:${netWeight}g"
|
||||||
|
val weightText = "${currentWeight.roundedOneDecimalPlace()}g"
|
||||||
|
text = weightText
|
||||||
|
tag = currentWeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//recognizeFood(netWeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (SpTool.cookMode == 1) {
|
||||||
|
// 采集模式:绑定搜索栏交互
|
||||||
|
binding.ivDishSearch.visible()
|
||||||
|
binding.etInputDish.isFocusable = true
|
||||||
|
binding.etInputDish.isFocusableInTouchMode = true
|
||||||
|
binding.ivDishSearch.setOnClickListener { jumpSearch() }
|
||||||
|
binding.etInputDish.addOnActionSearchListener { jumpSearch() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// binding.btnCook.clickWithDebounce {
|
||||||
|
// if (SpTool.cookMode == 1) {
|
||||||
|
// // 采集模式:从输入框创建 FoodRecord
|
||||||
|
// val showFoodName = binding.etInputDish.text.toString().trim()
|
||||||
|
// if (showFoodName.isBlank()) {
|
||||||
|
// toast("菜品名称为空")
|
||||||
|
// return@clickWithDebounce
|
||||||
|
// }
|
||||||
|
// if (list.isEmpty()) {
|
||||||
|
// toast("菜品构成信息未设置")
|
||||||
|
// return@clickWithDebounce
|
||||||
|
// }
|
||||||
|
// val foodRecord = FoodRecord().apply {
|
||||||
|
// foodId = mealItem?.foodId?.toString()
|
||||||
|
// foodName = showFoodName
|
||||||
|
// cookMode = 1
|
||||||
|
// }
|
||||||
|
// Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
|
||||||
|
// val submitList = list.map { it.toCookFoodGoodsEntity() }.toMutableList()
|
||||||
|
// startActivity<SubmitFoodActivity> {
|
||||||
|
// putExtra(SubmitFoodActivity.GOODS_LIST, submitList as Serializable)
|
||||||
|
// putExtra(SubmitFoodActivity.FOOD_ITEM, foodRecord as Serializable)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // 包装模式:检查食材是否全部设置完成
|
||||||
|
// val count = list.count { it.isSetFinished.not() }
|
||||||
|
// if (count > 0) {
|
||||||
|
// showRemindDialog()
|
||||||
|
// return@clickWithDebounce
|
||||||
|
// }
|
||||||
|
// openSubmitPage()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
binding.ivClearWeight.clickWithDebounce {
|
||||||
|
initialWeight = 0.0
|
||||||
|
WeightUtil.tareTwo(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivAddWeight.clickWithDebounce {
|
||||||
|
if(currentWeight <= 0.0) {
|
||||||
|
toast("当前秤重量无效")
|
||||||
|
return@clickWithDebounce
|
||||||
|
}
|
||||||
|
list.getOrNull(clickIndex)?.let {
|
||||||
|
it.useWeight = currentWeight
|
||||||
|
it.isSetFinished = true
|
||||||
|
materialAdapter.notifyItemChanged(clickIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.btnGetCode.clickWithDebounce {
|
||||||
|
val item = list.getOrNull(clickIndex)?:return@clickWithDebounce
|
||||||
|
//viewModelV2.getCode
|
||||||
|
}
|
||||||
|
binding.btnSubmit.clickWithDebounce {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private val isTakingPhoto = AtomicBoolean(false)
|
||||||
|
|
||||||
|
// ========== 重量识别相关变量已注释 ==========
|
||||||
|
// private var showRecognizePage = false
|
||||||
|
// private var pageVisible = true
|
||||||
|
// private var manualCancelFlag = false
|
||||||
|
// private var lastPhotoUri: Uri? = null
|
||||||
|
// private var lastWeight = 0.0
|
||||||
|
// private var currentWeight = 0.0
|
||||||
|
private var initialWeight = SpTool.configWeight.toDouble()
|
||||||
|
|
||||||
|
// private fun recognizeFood(weight: Double) {
|
||||||
|
// // 重量识别逻辑已注释
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新计算 list 中非接口数据(isOriginalData=false)的 materialType
|
||||||
|
*
|
||||||
|
* 规则:
|
||||||
|
* - 接口数据主材数量 n = list 中 isOriginalData=true 且 materialType=1 的数量
|
||||||
|
* - 有接口数据且 MATERIAL_COUNT - n <= 0:所有非接口数据均为辅材(2)
|
||||||
|
* - 无接口数据,或 MATERIAL_COUNT - n > 0:m = MATERIAL_COUNT - n,
|
||||||
|
* 非接口数据按 useWeight 从大到小排序,前 m 个为主材(1),其余为辅材(2)
|
||||||
|
*/
|
||||||
|
private fun updateMaterialTypes() {
|
||||||
|
val hasOriginalData = list.any { it.isOriginalData }
|
||||||
|
// 接口数据中主材数量
|
||||||
|
val n = list.count { it.isOriginalData && it.materialType == 1 }
|
||||||
|
// 待分配的非接口数据
|
||||||
|
val nonOriginalList = list.filter { !it.isOriginalData }
|
||||||
|
|
||||||
|
if (hasOriginalData && MATERIAL_COUNT - n <= 0) {
|
||||||
|
// 主材已满,所有非接口数据均为辅材
|
||||||
|
nonOriginalList.forEach { it.materialType = 2 }
|
||||||
|
} else {
|
||||||
|
// 剩余可分配主材名额
|
||||||
|
val m = MATERIAL_COUNT - n
|
||||||
|
// 按 useWeight 从大到小排序
|
||||||
|
val sorted = nonOriginalList.sortedByDescending { it.useWeight ?: 0.0 }
|
||||||
|
sorted.forEachIndexed { index, item ->
|
||||||
|
item.materialType = if (index < m) 1 else 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
materialAdapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openSubmitPage() {
|
||||||
|
getGoodsList()
|
||||||
|
if (goodsList.isNullOrEmpty()) {
|
||||||
|
toast("无菜品构成信息")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Log.d(TAG, "goToSubmit: goodsList:${goodsList?.toJsonString()}")
|
||||||
|
startActivity<SubmitFoodActivity> {
|
||||||
|
putExtra(SubmitFoodActivity.GOODS_LIST, goodsList as Serializable)
|
||||||
|
putExtra(SubmitFoodActivity.FOOD_ITEM, FoodRecord().apply {
|
||||||
|
foodId = mealItem?.foodId?.toString()
|
||||||
|
foodName = mealItem?.foodName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGoodsList() {
|
||||||
|
if (goodsList == null) {
|
||||||
|
goodsList = mutableListOf()
|
||||||
|
} else {
|
||||||
|
goodsList!!.clear()
|
||||||
|
}
|
||||||
|
// 将 Goods Item 转换为 CookFoodGoodsEntity 并补充菜品相关字段
|
||||||
|
list.filter { it.isSetFinished }.forEach {
|
||||||
|
goodsList?.add(it.toCookFoodGoodsEntity().apply {
|
||||||
|
foodId = mealItem?.foodId?.toString()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showRemindDialog() {
|
||||||
|
CommonDialog(this)
|
||||||
|
.setTitle(getString(R.string.food_remind_01))
|
||||||
|
.setContent(getString(R.string.food_remind_02))
|
||||||
|
.setNegativeButton("返回调整")
|
||||||
|
.setPositiveButton("确认无误") { openSubmitPage() }
|
||||||
|
.setOnDismissCallback { hideStatusBar() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initObserver() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
netViewModel.foodDetailState.collect { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val detail = state.data
|
||||||
|
if (detail == null) {
|
||||||
|
toast("查询菜品信息为空")
|
||||||
|
return@collect
|
||||||
|
}
|
||||||
|
loadDishDetail(detail)
|
||||||
|
}
|
||||||
|
is UiState.Error -> toast(state.msg)
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== getDishDetail 方法已删除,不再通过接口查询 ==========
|
||||||
|
|
||||||
|
private fun loadDishDetail(detail: CookFoodDTO) {
|
||||||
|
val voList = detail.foodConstituteList
|
||||||
|
if (voList.isNullOrEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 筛选出主材和辅材,转换为 Goods Item(useWeight 置零)
|
||||||
|
val tempData = voList.filter { it.materialType == 1 || it.materialType == 2 }
|
||||||
|
.map { it.toGoodsItem().also { item -> item.useWeight = 0.0 } }
|
||||||
|
// 直接替换 adapter.items
|
||||||
|
list.clear()
|
||||||
|
list.addAll(tempData)
|
||||||
|
materialAdapter.items = list
|
||||||
|
materialAdapter.notifyDataSetChanged()
|
||||||
|
firstReqSize = list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载餐品食材构成(从 NutFoodOptionVO.compositions 解析)
|
||||||
|
*/
|
||||||
|
private fun loadDishCompositions(compositions: List<NutFoodComposition>) {
|
||||||
|
// 将 NutFoodComposition 转换为 Goods Item
|
||||||
|
val tempData = compositions.map { comp ->
|
||||||
|
GoodsItem().apply {
|
||||||
|
goodsId = comp.materId?.toString() ?: ""
|
||||||
|
goodsName = comp.ingredientName ?: ""
|
||||||
|
materialType = if (comp.isMain == 1) 1 else 2
|
||||||
|
useWeight = 0.0
|
||||||
|
isOriginalData = true
|
||||||
|
isSetFinished = false
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
|
||||||
|
list.clear()
|
||||||
|
list.addAll(tempData)
|
||||||
|
materialAdapter.items = list
|
||||||
|
materialAdapter.notifyDataSetChanged()
|
||||||
|
firstReqSize = list.size
|
||||||
|
}
|
||||||
|
|
||||||
|
private var firstReqSize = 0
|
||||||
|
private val list = mutableListOf<GoodsItem>()
|
||||||
|
private var clickIndex = -1
|
||||||
|
private val materialAdapter by lazy {
|
||||||
|
FoodMaterialAdapter(list).apply {
|
||||||
|
onItemClick = { positon ->
|
||||||
|
this@PackActivity.clickIndex = positon
|
||||||
|
list.forEachIndexed { index, entity ->
|
||||||
|
entity.isClicked = index == positon
|
||||||
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, position ->
|
||||||
|
val item = list.getOrNull(position) ?: return@addOnItemChildClickListener
|
||||||
|
Log.d(TAG, "onFoodItemClick: ${item.toJsonString()}")
|
||||||
|
if (item.isOriginalData) {
|
||||||
|
// 无重量信息时转为 item 整体点击(触发选中效果)
|
||||||
|
if (item.useWeight == null || item.useWeight == 0.0) {
|
||||||
|
onItemClick?.invoke(position)
|
||||||
|
return@addOnItemChildClickListener
|
||||||
|
}
|
||||||
|
deleteRemindDialog("清除确认", "确定清除食材「${item.goodsName}」添加的重量吗?") {
|
||||||
|
item.run {
|
||||||
|
isNewDishType = false
|
||||||
|
useWeight = 0.0
|
||||||
|
isSetFinished = false
|
||||||
|
}
|
||||||
|
notifyItemChanged(position)
|
||||||
|
}
|
||||||
|
return@addOnItemChildClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRemindDialog("删除确认", "确定删除食材「${item.goodsName}」吗?") {
|
||||||
|
removeFood(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RecyclerView初始化
|
||||||
|
*/
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.rvMaterialList.let {
|
||||||
|
it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
|
// 仅 isNewDishType=true 的 item 显示侧滑删除菜单(必须在 setAdapter 之前调用)
|
||||||
|
it.setSwipeMenuCreator { _, rightMenu, position ->
|
||||||
|
if (list.getOrNull(position)?.isNewDishType == true) {
|
||||||
|
rightMenu.addMenuItem(buildDeleteMenuItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 点击侧滑菜单项:先关闭菜单,再弹窗确认删除
|
||||||
|
it.setOnItemMenuClickListener { menuBridge, position ->
|
||||||
|
menuBridge.closeMenu()
|
||||||
|
val item = list.getOrNull(position) ?: return@setOnItemMenuClickListener
|
||||||
|
deleteRemindDialog("删除确认", "确定删除食材「${item.goodsName}」吗?") {
|
||||||
|
removeFood(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// item 点击事件
|
||||||
|
it.setOnItemClickListener { _, position ->
|
||||||
|
materialAdapter.onItemClick?.invoke(position)
|
||||||
|
}
|
||||||
|
handleRvTouchHideKeyboard()
|
||||||
|
it.adapter = materialAdapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除提醒
|
||||||
|
*/
|
||||||
|
private fun deleteRemindDialog(title: String, content: String, action: () -> Unit) {
|
||||||
|
CommonDialog(this@PackActivity)
|
||||||
|
.setTitle(title)
|
||||||
|
.setContent(content)
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("确认") {
|
||||||
|
action()
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除菜品
|
||||||
|
*/
|
||||||
|
private fun removeFood(position: Int) {
|
||||||
|
materialAdapter.removeAt(position)
|
||||||
|
toast("已删除")
|
||||||
|
updateMaterialTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建侧滑删除菜单项
|
||||||
|
*/
|
||||||
|
private fun buildDeleteMenuItem(): SwipeMenuItem {
|
||||||
|
return SwipeMenuItem(this).apply {
|
||||||
|
setImage(R.drawable.ic_trash_white)
|
||||||
|
setBackground(R.drawable.bg_swipe_delete)
|
||||||
|
width = 160.dp
|
||||||
|
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
// pageVisible = true
|
||||||
|
// showRecognizePage = false
|
||||||
|
cameraUtils.bind()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
// pageVisible = false
|
||||||
|
cameraUtils.unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化相机并绑定预览容器
|
||||||
|
* @param container 相机预览容器
|
||||||
|
*/
|
||||||
|
fun initCamera(container: ViewGroup) {
|
||||||
|
cameraUtils.initCamera()
|
||||||
|
val previewBinding = LayoutCameraPreviewBinding.inflate(layoutInflater, container)
|
||||||
|
cameraUtils.setPreviewController(previewBinding.previewView)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册返回键监听,替代已废弃的 onBackPressed()
|
||||||
|
*/
|
||||||
|
private fun addBackKeyListener() {
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
if (SpTool.cookMode == 1) {
|
||||||
|
// 采集模式:有新增食材时提示保存
|
||||||
|
if (list.isEmpty().not()) {
|
||||||
|
saveDataRemindDialog()
|
||||||
|
return@addCallback
|
||||||
|
}
|
||||||
|
if (pageFrom == HOME) {
|
||||||
|
startActivity<SamplingModeActivity>()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 包装模式:有未保存数据时提示
|
||||||
|
val count = list.count { !it.isOriginalData }
|
||||||
|
if (count > 0) {
|
||||||
|
saveDataRemindDialog()
|
||||||
|
return@addCallback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未保存数据提醒
|
||||||
|
*/
|
||||||
|
private fun saveDataRemindDialog() {
|
||||||
|
CommonDialog(this)
|
||||||
|
.setTitle("返回提示")
|
||||||
|
.setContent("您好,当前页面存在未保存的数据,\n确认返回吗?")
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("确认") {
|
||||||
|
if (SpTool.cookMode == 1 && pageFrom == HOME) {
|
||||||
|
startActivity<SamplingModeActivity>()
|
||||||
|
}
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
.setOnDismissCallback { hideStatusBar() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 拍照回调相关功能已注释 ==========
|
||||||
|
// private val cameraSuccessCallback: (Uri) -> Unit = { uri ->
|
||||||
|
// // 拍照成功回调已注释
|
||||||
|
// }
|
||||||
|
// private var notRecognizeDialog: CommonDialog? = null
|
||||||
|
// private fun showNotRecognizeDialog() {
|
||||||
|
// // 未识别弹窗已注释
|
||||||
|
// }
|
||||||
|
// private val cameraFailureCallback: (String) -> Unit = { errMsg ->
|
||||||
|
// // 拍照失败回调已注释
|
||||||
|
// }
|
||||||
|
// private fun loadRecognizeResultPage(nameScoreList: List<FoodModule.IdNameScore>) {
|
||||||
|
// // 识别结果页加载已注释
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转食物搜索页(采集模式专用)
|
||||||
|
*/
|
||||||
|
private fun jumpSearch() {
|
||||||
|
val searchContent = binding.etInputDish.text.toString().trim()
|
||||||
|
if (searchContent.isBlank()) {
|
||||||
|
toast(binding.etInputDish.hint.toString())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val launchIntent = Intent(this, FoodSearchActivity::class.java).apply {
|
||||||
|
putExtra(FoodSearchActivity.FOOD_NAME, searchContent)
|
||||||
|
}
|
||||||
|
startActivity(launchIntent) { resultIntent ->
|
||||||
|
if (resultIntent == null) return@startActivity
|
||||||
|
val food = IntentCompat.getSerializableExtra(resultIntent, FoodSearchActivity.FOOD_ITEM, FoodRecord::class.java)
|
||||||
|
Log.d(TAG, "jumpSearch: record=$food")
|
||||||
|
if (food == null) return@startActivity
|
||||||
|
binding.etInputDish.run {
|
||||||
|
setText(food.foodName)
|
||||||
|
tag = food.foodName
|
||||||
|
setSelection(text.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideKeyboard()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRvTouchHideKeyboard() {
|
||||||
|
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
|
||||||
|
override fun onSingleTapUp(e: MotionEvent): Boolean {
|
||||||
|
hideKeyboard()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
binding.rvMaterialList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
||||||
|
private var startX = 0f
|
||||||
|
private var startY = 0f
|
||||||
|
|
||||||
|
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
|
||||||
|
when (e.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
startX = e.x
|
||||||
|
startY = e.y
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
val dx = abs(e.x - startX)
|
||||||
|
val dy = abs(e.y - startY)
|
||||||
|
if (dx > dy && dx > 10) {
|
||||||
|
hideKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gestureDetector.onTouchEvent(e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:background="@drawable/bg_other_page">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_margin="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="餐品列表"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvMealList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
tools:itemCount="3"
|
||||||
|
tools:listitem="@layout/list_item_food2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:background="@drawable/bg_other_page">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llSearchBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_margin="30dp"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etInputDish"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginHorizontal="28dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:autofillHints=""
|
||||||
|
android:background="@color/white"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:hint="@string/dish_search_hint"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="3dp"
|
||||||
|
android:paddingEnd="3dp"
|
||||||
|
android:textColor="@color/black333"
|
||||||
|
android:textColorHint="@color/gray_c8"
|
||||||
|
android:textSize="40sp"
|
||||||
|
tools:ignore="TextFields" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivDishSearch"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:src="@drawable/ic_search_gray"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvGoodsName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="豆腐" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMaterialType"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp"
|
||||||
|
tools:text="主材" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnGetCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:paddingHorizontal="20dp"
|
||||||
|
android:text="获取溯源码"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:background="@drawable/ripple_effect_light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
app:dividerColor="@color/gray_eb" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="160dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:text="用量(克)"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvShowWeight"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_f6_10_corners"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="-"
|
||||||
|
android:textColor="@color/gray_d6"
|
||||||
|
android:textSize="50sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivClearWeight"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:src="@drawable/ic_weight_clear" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivAddWeight"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:src="@drawable/ic_weight_add" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:text="在下方列表中选择食材计重"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:layout_marginVertical="30dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="@string/dish_composition"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
<!-- 重量显示已注释,重量识别功能整体已移除 -->
|
||||||
|
<!--
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvShowWeight"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:paddingHorizontal="30dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="28sp" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/flCameraContainer"
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="1dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||||
|
android:id="@+id/rvMaterialList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
tools:itemCount="3"
|
||||||
|
tools:listitem="@layout/list_item_food_material" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnSubmit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_margin="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" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user