feat(activity): 新增食材识别页面,重构识别流程并优化多设备布局适配
This commit is contained in:
@@ -111,6 +111,11 @@
|
|||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
|
<activity
|
||||||
|
android:name="com.shuwei.dish.match.ui.FoodRecognizeActivity"
|
||||||
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name="com.shuwei.dish.match.ui.SlaveActivity"
|
android:name="com.shuwei.dish.match.ui.SlaveActivity"
|
||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ class Scale18GridAdapter : BaseQuickAdapter<ScaleData, Scale18GridAdapter.VH>(mu
|
|||||||
b.root.layoutParams = (b.root.layoutParams as ViewGroup.MarginLayoutParams).also {
|
b.root.layoutParams = (b.root.layoutParams as ViewGroup.MarginLayoutParams).also {
|
||||||
it.width = cellSize
|
it.width = cellSize
|
||||||
it.height = cellSize
|
it.height = cellSize
|
||||||
it.setMargins(margin, margin, margin, margin)
|
// 第1行:顶部间距为0,底部间距2dp,左右保持原有 margin
|
||||||
|
if (viewType == 0) it.setMargins(margin, 0, margin, 2.dp)
|
||||||
|
else it.setMargins(margin, margin, margin, margin)
|
||||||
}
|
}
|
||||||
val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt()
|
val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt()
|
||||||
b.tvAddr.textSize = (baseSp * 0.16f).coerceIn(9f, 14f)
|
b.tvAddr.textSize = (baseSp * 0.16f).coerceIn(9f, 14f)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.shuwei.dish.match.entity.SeasoningEntity
|
|||||||
import com.shuwei.dish.match.net.NetViewModel
|
import com.shuwei.dish.match.net.NetViewModel
|
||||||
import com.shuwei.dish.match.ui.InitActivity
|
import com.shuwei.dish.match.ui.InitActivity
|
||||||
import com.shuwei.dish.match.utils.ActivityManager
|
import com.shuwei.dish.match.utils.ActivityManager
|
||||||
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.invisible
|
import com.shuwei.dish.match.utils.ext.invisible
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
@@ -65,6 +66,10 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
// systemBarsBehavior =
|
// systemBarsBehavior =
|
||||||
// WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // 滑动时临时显示
|
// WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE // 滑动时临时显示
|
||||||
// }
|
// }
|
||||||
|
// 主设备垂直 padding 30dp,子设备 15dp
|
||||||
|
val verticalPadding = if (GlobalData.deviceRole == DeviceRole.MASTER) 30.dp else 10.dp
|
||||||
|
binding.tvLeftTime.setPadding(0, verticalPadding, 0, verticalPadding)
|
||||||
|
binding.tvRightTime.setPadding(0, verticalPadding, 0, verticalPadding)
|
||||||
binding.llTitleBar.gone()
|
binding.llTitleBar.gone()
|
||||||
binding.ivBack.setOnClickListener { finish() }
|
binding.ivBack.setOnClickListener { finish() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ import android.graphics.drawable.ColorDrawable
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
|
import android.widget.LinearLayout
|
||||||
import androidx.annotation.StyleRes
|
import androidx.annotation.StyleRes
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import com.shuwei.dish.match.base.DeviceRole
|
||||||
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
import com.shuwei.dish.match.databinding.DialogCommonBinding
|
import com.shuwei.dish.match.databinding.DialogCommonBinding
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
@@ -55,12 +59,17 @@ open class CommonDialog(
|
|||||||
binding = DialogCommonBinding.inflate(layoutInflater)
|
binding = DialogCommonBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
window?.run {
|
window?.run {
|
||||||
|
val screenWidth = context.resources.displayMetrics.widthPixels
|
||||||
|
val isMaster = GlobalData.deviceRole == DeviceRole.MASTER
|
||||||
attributes = attributes.apply {
|
attributes = attributes.apply {
|
||||||
width = 660.dp
|
width = if (isMaster) (screenWidth * 0.72f).toInt() else (screenWidth * 0.60f).toInt()
|
||||||
}
|
}
|
||||||
setBackgroundDrawable(ColorDrawable())
|
setBackgroundDrawable(ColorDrawable())
|
||||||
setCancelable(false)
|
setCancelable(false)
|
||||||
}
|
}
|
||||||
|
val verticalMargin = if (GlobalData.deviceRole == DeviceRole.MASTER) 35.dp else 20.dp
|
||||||
|
binding.tvTitle.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = verticalMargin }
|
||||||
|
binding.tvContent.updateLayoutParams<LinearLayout.LayoutParams> { bottomMargin = verticalMargin }
|
||||||
binding.btnLeft.setOnClickListener {
|
binding.btnLeft.setOnClickListener {
|
||||||
negativeClick?.invoke()
|
negativeClick?.invoke()
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ class LoadingDialog(
|
|||||||
setCancelable(true)
|
setCancelable(true)
|
||||||
window?.run {
|
window?.run {
|
||||||
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
setBackgroundDrawable(Color.TRANSPARENT.toDrawable())
|
||||||
setFlags(
|
// setFlags(
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
// WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||||
);
|
// );
|
||||||
}
|
}
|
||||||
setOnDismissListener {
|
setOnDismissListener {
|
||||||
onDismiss()
|
onDismiss()
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
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
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 食材识别结果页面
|
||||||
|
* 展示识别到的食材照片、食材列表、选中食材名称及秤1重量
|
||||||
|
*/
|
||||||
|
class FoodRecognizeActivity : BaseActivity() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "FoodRecognizeActivity"
|
||||||
|
private const val EXTRA_IMAGE_URI = "extra_image_uri"
|
||||||
|
const val EXTRA_SELECTED_ITEM = "extra_selected_item"
|
||||||
|
|
||||||
|
/** 内存缓存食材列表,避免通过 Intent 序列化传递大数据 */
|
||||||
|
private var pendingGoodsList: ArrayList<CookFoodGoodsEntity>? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动本页面,通过 onResult 回调返回用户选中的食材
|
||||||
|
* @param activity 宿主 Activity
|
||||||
|
* @param imageUri 食材照片路径(可为空)
|
||||||
|
* @param goodsList 识别到的食材列表
|
||||||
|
* @param onResult 页面关闭后回调,携带用户选中的食材(未选中时为 null)
|
||||||
|
*/
|
||||||
|
fun start(
|
||||||
|
activity: BaseActivity,
|
||||||
|
imageUri: String? = null,
|
||||||
|
goodsList: ArrayList<CookFoodGoodsEntity> = arrayListOf(),
|
||||||
|
onResult: (CookFoodGoodsEntity?) -> Unit = {}
|
||||||
|
) {
|
||||||
|
pendingGoodsList = goodsList
|
||||||
|
val intent = Intent(activity, FoodRecognizeActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_IMAGE_URI, imageUri)
|
||||||
|
}
|
||||||
|
activity.startActivity(intent) { resultIntent ->
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
val item = resultIntent?.getSerializableExtra(EXTRA_SELECTED_ITEM) as? CookFoodGoodsEntity
|
||||||
|
onResult(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭当前识别页面,并将选中食材通过 Activity Result 回传
|
||||||
|
* 由外部(如重量归零时)调用
|
||||||
|
*/
|
||||||
|
fun close() {
|
||||||
|
ActivityManager.getActivityStack()
|
||||||
|
.filterIsInstance<FoodRecognizeActivity>()
|
||||||
|
.lastOrNull()
|
||||||
|
?.finishWithResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityFoodRecognizeBinding
|
||||||
|
|
||||||
|
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||||
|
|
||||||
|
private val adapter = GoodsInfoSearchAdapter(list).apply {
|
||||||
|
setOnItemClickListener { _, _, position ->
|
||||||
|
// 更新选中状态
|
||||||
|
list.forEachIndexed { i, item -> item.isClicked = (i == position) }
|
||||||
|
notifyDataSetChanged()
|
||||||
|
// 同步更新选中食材名称
|
||||||
|
binding.tvSelectedFood.text = list[position].goodsName ?: "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityFoodRecognizeBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
|
||||||
|
// 显示标题栏
|
||||||
|
setTitleBar(titleBarAction = { it.visible() }, titleAction = { it.text = "食材识别" })
|
||||||
|
|
||||||
|
initData()
|
||||||
|
initRecyclerView()
|
||||||
|
initClickListeners()
|
||||||
|
registerWeightListener()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Intent 读取数据并初始化页面
|
||||||
|
*/
|
||||||
|
private fun initData() {
|
||||||
|
// 加载食材照片
|
||||||
|
val imageUri = intent.getStringExtra(EXTRA_IMAGE_URI)
|
||||||
|
if (!imageUri.isNullOrBlank()) {
|
||||||
|
binding.ivFoodPhoto.setImageURI(Uri.parse(imageUri))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取出内存缓存的食材列表,取用后立即清空
|
||||||
|
val goodsList = pendingGoodsList?.also { pendingGoodsList = null }
|
||||||
|
if (!goodsList.isNullOrEmpty()) {
|
||||||
|
list.addAll(goodsList)
|
||||||
|
// 默认选中第一项
|
||||||
|
list[0].isClicked = true
|
||||||
|
binding.tvSelectedFood.text = list[0].goodsName ?: "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 RecyclerView
|
||||||
|
*/
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.recyclerView.run {
|
||||||
|
layoutManager = GridLayoutManager(this@FoodRecognizeActivity, 2)
|
||||||
|
adapter = this@FoodRecognizeActivity.adapter
|
||||||
|
}
|
||||||
|
updateListVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据列表是否有数据控制 RecyclerView 显隐
|
||||||
|
*/
|
||||||
|
private fun updateListVisibility() {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
binding.recyclerView.gone()
|
||||||
|
} else {
|
||||||
|
binding.recyclerView.visible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化按钮点击事件
|
||||||
|
*/
|
||||||
|
private fun initClickListeners() {
|
||||||
|
// 更换食材:打开食材搜索弹窗
|
||||||
|
binding.btnChangeFood.clickWithDebounce {
|
||||||
|
val currentName = if (list.isNotEmpty()) list.firstOrNull { it.isClicked }?.goodsName else null
|
||||||
|
FoodSearchDialog(
|
||||||
|
activity = this,
|
||||||
|
defGoodsName = currentName,
|
||||||
|
onItemSelected = { item ->
|
||||||
|
// 用搜索结果替换当前选中食材
|
||||||
|
updateSelectedFood(item)
|
||||||
|
}
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消:关闭页面
|
||||||
|
binding.btnCancel.setOnClickListener { finish() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用新食材替换当前选中项(或追加到列表首位)
|
||||||
|
*/
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun updateSelectedFood(item: CookFoodGoodsEntity) {
|
||||||
|
item.isClicked = true
|
||||||
|
val clickedIndex = list.indexOfFirst { it.isClicked && it.goodsId != item.goodsId }
|
||||||
|
if (clickedIndex >= 0) {
|
||||||
|
list[clickedIndex].isClicked = false
|
||||||
|
}
|
||||||
|
// 若列表中已存在则直接选中,否则插入到首位
|
||||||
|
val existIndex = list.indexOfFirst { it.goodsId == item.goodsId }
|
||||||
|
if (existIndex >= 0) {
|
||||||
|
list.forEachIndexed { i, e -> e.isClicked = (i == existIndex) }
|
||||||
|
} else {
|
||||||
|
list.add(0, item)
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
binding.tvSelectedFood.text = item.goodsName ?: "-"
|
||||||
|
updateListVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册秤1重量监听
|
||||||
|
*/
|
||||||
|
private fun registerWeightListener() {
|
||||||
|
WeightUtil.addWeightListener(TAG) { address, _, weight ->
|
||||||
|
if (address == AddressUtil.ONE) {
|
||||||
|
runOnUiThread {
|
||||||
|
binding.tvWeight.text = "$weight g"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 携带当前选中食材关闭页面
|
||||||
|
*/
|
||||||
|
private fun finishWithResult() {
|
||||||
|
val selected = list.firstOrNull { it.isClicked }
|
||||||
|
val intent = Intent().apply {
|
||||||
|
selected?.let { putExtra(EXTRA_SELECTED_ITEM, it) }
|
||||||
|
}
|
||||||
|
setResult(RESULT_OK, intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
WeightUtil.removeWeightListener(TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ import com.shuwei.dish.match.adapter.DishPartAdapter
|
|||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.databinding.ActivityPrepareCookBinding
|
import com.shuwei.dish.match.databinding.ActivityPrepareCookBinding
|
||||||
import com.shuwei.dish.match.dialog.CommonDialog
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
import com.shuwei.dish.match.dialog.FoodRecognizeDialog
|
|
||||||
import com.shuwei.dish.match.dialog.FoodSearchDialog
|
import com.shuwei.dish.match.dialog.FoodSearchDialog
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
||||||
@@ -158,6 +157,10 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val isTakingPhoto = AtomicBoolean(false)
|
private val isTakingPhoto = AtomicBoolean(false)
|
||||||
|
private var isRecognizeOpen = false
|
||||||
|
// 页面可见时允许识别,onPause 后禁止,onResume 后恢复
|
||||||
|
private var isRecognizeEnabled = true
|
||||||
|
private var lastPhotoUri: Uri? = null
|
||||||
private var lastWeight = 0.0
|
private var lastWeight = 0.0
|
||||||
private var currentWeight = 0.0
|
private var currentWeight = 0.0
|
||||||
|
|
||||||
@@ -168,10 +171,11 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
private fun recognizeFood(weight: Double) {
|
private fun recognizeFood(weight: Double) {
|
||||||
this.currentWeight = weight
|
this.currentWeight = weight
|
||||||
if (weight < WEIGHT_RECOGNIZE_VALUE) {
|
if (weight < WEIGHT_RECOGNIZE_VALUE) {
|
||||||
if (recognizeDialog.isShowing) recognizeDialog.dismiss()
|
isRecognizeOpen = false
|
||||||
|
FoodRecognizeActivity.close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (isTakingPhoto.get() || recognizeDialog.isShowing || abs(lastWeight - weight) <= WEIGHT_CHANGE_VALUE) return
|
if (!isRecognizeEnabled || isTakingPhoto.get() || isRecognizeOpen || abs(lastWeight - weight) <= WEIGHT_CHANGE_VALUE) return
|
||||||
isTakingPhoto.set(true)
|
isTakingPhoto.set(true)
|
||||||
cameraUtils.takePhoto(
|
cameraUtils.takePhoto(
|
||||||
succCallback = cameraSuccessCallback,
|
succCallback = cameraSuccessCallback,
|
||||||
@@ -194,9 +198,13 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
// materialType =
|
// materialType =
|
||||||
isNewDishType = true
|
isNewDishType = true
|
||||||
isOriginalData = false
|
isOriginalData = false
|
||||||
|
useWeight = lastWeight
|
||||||
|
isSetFinished = true
|
||||||
})
|
})
|
||||||
onFoodItemClick(list.size - 1)
|
val positon = list.size - 1
|
||||||
binding.rvDishPartList.smoothScrollToPosition(list.size - 1)
|
dishPartAdapter.notifyItemInserted(positon)
|
||||||
|
onFoodItemClick(positon)
|
||||||
|
binding.rvDishPartList.smoothScrollToPosition(positon)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -298,18 +306,24 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
|
|
||||||
private var firstReqSize = 0
|
private var firstReqSize = 0
|
||||||
private val list = mutableListOf<CookFoodGoodsEntity>()
|
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||||
private val recognizeDialog by lazy {
|
|
||||||
FoodRecognizeDialog(
|
|
||||||
activity = this,
|
|
||||||
onDismiss = { isTakingPhoto.set(false) },
|
|
||||||
onItemSelected = foodSelectCallback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
private val dishPartAdapter by lazy {
|
private val dishPartAdapter by lazy {
|
||||||
DishPartAdapter(list).apply {
|
DishPartAdapter(list).apply {
|
||||||
setOnItemClickListener { _, _, positon ->
|
setOnItemClickListener { _, _, positon ->
|
||||||
onFoodItemClick(positon)
|
onFoodItemClick(positon)
|
||||||
}
|
}
|
||||||
|
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, positon ->
|
||||||
|
if (list[positon].isOriginalData) {
|
||||||
|
list[positon].run {
|
||||||
|
isNewDishType = false
|
||||||
|
isOriginalData = false
|
||||||
|
useWeight = 0.0
|
||||||
|
isSetFinished = false
|
||||||
|
}
|
||||||
|
notifyItemChanged(positon)
|
||||||
|
return@addOnItemChildClickListener
|
||||||
|
}
|
||||||
|
removeAt(positon)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,11 +402,14 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
isRecognizeEnabled = true
|
||||||
|
isRecognizeOpen = false
|
||||||
cameraUtils.bind()
|
cameraUtils.bind()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
isRecognizeEnabled = false
|
||||||
cameraUtils.unbind()
|
cameraUtils.unbind()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +455,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private val cameraSuccessCallback: (Uri) -> Unit = { uri ->
|
private val cameraSuccessCallback: (Uri) -> Unit = { uri ->
|
||||||
Log.d(TAG, "takePhoto success")
|
Log.d(TAG, "takePhoto success")
|
||||||
|
lastPhotoUri = uri
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val bitmap = ImageUtil.uriToBitmap(this@PrepareCookActivity, uri)
|
val bitmap = ImageUtil.uriToBitmap(this@PrepareCookActivity, uri)
|
||||||
@@ -485,7 +503,13 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
foodId = index.toString()
|
foodId = index.toString()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
recognizeDialog.loadData(foodList)
|
FoodRecognizeActivity.start(
|
||||||
|
activity = this,
|
||||||
|
imageUri = lastPhotoUri?.toString(),
|
||||||
|
goodsList = ArrayList(foodList),
|
||||||
|
onResult = { item -> item?.let { foodSelectCallback(it) } }
|
||||||
|
)
|
||||||
|
isRecognizeOpen = true
|
||||||
isTakingPhoto.set(false)
|
isTakingPhoto.set(false)
|
||||||
lastWeight = currentWeight
|
lastWeight = currentWeight
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import android.widget.LinearLayout
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import com.google.android.flexbox.AlignItems
|
import com.google.android.flexbox.AlignItems
|
||||||
import com.google.android.flexbox.FlexDirection
|
import com.google.android.flexbox.FlexDirection
|
||||||
@@ -74,7 +76,11 @@ class SlaveActivity : BaseActivity() {
|
|||||||
val smallSize = usable / 9
|
val smallSize = usable / 9
|
||||||
val largeSize = (usable - smallSize * 6) / 2
|
val largeSize = (usable - smallSize * 6) / 2
|
||||||
val rvHeight = smallSize * 3 + 3 * 4.dp
|
val rvHeight = smallSize * 3 + 3 * 4.dp
|
||||||
binding.rvScaleList.layoutParams = binding.rvScaleList.layoutParams.also { it.height = rvHeight }
|
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> {
|
||||||
|
height = rvHeight
|
||||||
|
weight = 0f
|
||||||
|
topMargin = 20.dp
|
||||||
|
}
|
||||||
binding.rvScaleList.layoutManager = FlexboxLayoutManager(this).apply {
|
binding.rvScaleList.layoutManager = FlexboxLayoutManager(this).apply {
|
||||||
flexDirection = FlexDirection.COLUMN
|
flexDirection = FlexDirection.COLUMN
|
||||||
flexWrap = FlexWrap.WRAP
|
flexWrap = FlexWrap.WRAP
|
||||||
@@ -86,6 +92,7 @@ class SlaveActivity : BaseActivity() {
|
|||||||
binding.rvScaleList.adapter = scale22Adapter
|
binding.rvScaleList.adapter = scale22Adapter
|
||||||
}
|
}
|
||||||
ScaleDeviceConfig.DEVICE_ID_18 -> {
|
ScaleDeviceConfig.DEVICE_ID_18 -> {
|
||||||
|
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = 0 }
|
||||||
binding.rvScaleList.layoutManager = GridLayoutManager(this, 6).apply {
|
binding.rvScaleList.layoutManager = GridLayoutManager(this, 6).apply {
|
||||||
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||||
override fun getSpanSize(position: Int) = 1
|
override fun getSpanSize(position: Int) = 1
|
||||||
@@ -97,6 +104,7 @@ class SlaveActivity : BaseActivity() {
|
|||||||
binding.rvScaleList.adapter = scale18Adapter
|
binding.rvScaleList.adapter = scale18Adapter
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = 20.dp }
|
||||||
binding.rvScaleList.layoutManager = LinearLayoutManager(this)
|
binding.rvScaleList.layoutManager = LinearLayoutManager(this)
|
||||||
linearAdapter.setOnItemClickListener { _, _, position ->
|
linearAdapter.setOnItemClickListener { _, _, position ->
|
||||||
val item = linearAdapter.items.getOrNull(position) ?: return@setOnItemClickListener
|
val item = linearAdapter.items.getOrNull(position) ?: return@setOnItemClickListener
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
@@ -21,8 +21,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingTop="30dp"
|
|
||||||
android:paddingBottom="30dp"
|
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textSize="28sp"
|
android:textSize="28sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?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"
|
||||||
|
android:padding="16dp"
|
||||||
|
tools:background="@color/white">
|
||||||
|
|
||||||
|
<!-- 食材照片,权重占满剩余空间 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivFoodPhoto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:src="@color/bg_color" />
|
||||||
|
|
||||||
|
<!-- 识别到的食材列表,无数据时隐藏 -->
|
||||||
|
<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:overScrollMode="never"
|
||||||
|
android:visibility="gone"
|
||||||
|
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" />
|
||||||
|
|
||||||
|
<!-- 秤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" />
|
||||||
|
|
||||||
|
<!-- 更换食材 -->
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnChangeFood"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:background="@drawable/shape_green_bg"
|
||||||
|
android:text="更换食材"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<!-- 取消 -->
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
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:text="取消"
|
||||||
|
android:textColor="@color/black333"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -4,20 +4,36 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="12dp"
|
android:paddingHorizontal="5dp"
|
||||||
tools:background="@color/bg_color">
|
tools:background="@color/bg_color">
|
||||||
|
|
||||||
<!-- 本机IP地址 -->
|
<!-- IP 与主设备状态同行显示 -->
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/tvDeviceIp"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_marginTop="0dp"
|
android:gravity="center">
|
||||||
android:textSize="22sp"
|
|
||||||
android:textStyle="bold"
|
<!-- 本机IP地址 -->
|
||||||
android:textColor="@color/home_title"
|
<TextView
|
||||||
tools:text="IP:192.168.1.100" />
|
android:id="@+id/tvDeviceIp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/home_title"
|
||||||
|
tools:text="IP:192.168.1.100" />
|
||||||
|
|
||||||
|
<!-- 主设备连接状态 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvMasterStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:text="主设备:未连接" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- 设备信息 -->
|
<!-- 设备信息 -->
|
||||||
<TextView
|
<TextView
|
||||||
@@ -25,22 +41,10 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginTop="0dp"
|
android:textSize="16sp"
|
||||||
android:textSize="18sp"
|
|
||||||
android:textColor="@color/home_sub_title"
|
android:textColor="@color/home_sub_title"
|
||||||
tools:text="设备:device_02" />
|
tools:text="设备:device_02" />
|
||||||
|
|
||||||
<!-- 主设备连接状态 -->
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvMasterStatus"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:textSize="16sp"
|
|
||||||
tools:text="主设备:未连接" />
|
|
||||||
|
|
||||||
<!-- 本机秤数据列表 -->
|
<!-- 本机秤数据列表 -->
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rvScaleList"
|
android:id="@+id/rvScaleList"
|
||||||
|
|||||||
@@ -46,11 +46,22 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ivOperateIcon"
|
android:id="@+id/ivOperateIcon"
|
||||||
android:layout_width="60dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginEnd="30dp"
|
|
||||||
tools:src="@drawable/ic_dish_selected"
|
tools:src="@drawable/ic_dish_selected"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/ivClearIcon"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivClearIcon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
tools:src="@drawable/ic_dish_clear"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|||||||
Reference in New Issue
Block a user