Compare commits
9
Commits
b6b5088107
...
75830b9204
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75830b9204 | ||
|
|
0498501b33 | ||
|
|
8c709a3f5f | ||
|
|
9ba6443f4f | ||
|
|
04e4efe1fc | ||
|
|
bce9675b0f | ||
|
|
f25108360b | ||
|
|
4ec02ac2bc | ||
|
|
97b357850c |
@@ -106,6 +106,10 @@
|
|||||||
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.SingleFragmentActivity"
|
||||||
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name="com.shuwei.dish.match.ui.FoodRecognizeActivity"
|
android:name="com.shuwei.dish.match.ui.FoodRecognizeActivity"
|
||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
@@ -25,7 +26,8 @@ import com.shuwei.dish.match.utils.ext.dp
|
|||||||
*/
|
*/
|
||||||
class Seasoning18GridAdapter(
|
class Seasoning18GridAdapter(
|
||||||
private val showNameOnly: Boolean = false,
|
private val showNameOnly: Boolean = false,
|
||||||
private val showAddress: Boolean = false
|
private val showAddress: Boolean = false,
|
||||||
|
private val leftRightSpace: Int = 10.dp
|
||||||
) : BaseQuickAdapter<ScaleData, Seasoning18GridAdapter.VH>(mutableListOf()) {
|
) : BaseQuickAdapter<ScaleData, Seasoning18GridAdapter.VH>(mutableListOf()) {
|
||||||
|
|
||||||
/** 空位哨兵,address=0 表示无效 */
|
/** 空位哨兵,address=0 表示无效 */
|
||||||
@@ -47,12 +49,12 @@ class Seasoning18GridAdapter(
|
|||||||
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
|
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
val margin = if (viewType == 0) 12.dp else 2.dp
|
val margin = if (viewType == 0) 12.dp else 2.dp
|
||||||
val screenWidth = parent.resources.displayMetrics.widthPixels
|
val screenWidth = parent.resources.displayMetrics.widthPixels
|
||||||
val cellSize = (screenWidth - 6 * margin * 2 - 10.dp) / 6
|
val cellSize = (screenWidth - 6 * margin * 2 - leftRightSpace) / 6
|
||||||
(b.root.layoutParams as? ViewGroup.MarginLayoutParams)?.also {
|
b.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
it.width = cellSize
|
width = cellSize
|
||||||
it.height = cellSize
|
height = cellSize
|
||||||
if (viewType == 0) it.setMargins(margin, 0, margin, 2.dp)
|
if (viewType == 0) setMargins(margin, 0, margin, 2.dp)
|
||||||
else it.setMargins(margin, margin, margin, margin)
|
else setMargins(margin, margin, margin, margin)
|
||||||
}
|
}
|
||||||
val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt()
|
val baseSp = (cellSize / parent.resources.displayMetrics.density).toInt()
|
||||||
b.tvAddress.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
|
b.tvAddress.textSize = (baseSp * 0.14f).coerceIn(8f, 12f)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
@@ -51,7 +52,7 @@ class Seasoning22GridAdapter(
|
|||||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
|
val b = ListItemScale22RowBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
val cellSize = if (viewType == 1) largeSize else smallSize
|
val cellSize = if (viewType == 1) largeSize else smallSize
|
||||||
(b.root.layoutParams as? FlexboxLayoutManager.LayoutParams)?.apply {
|
b.root.updateLayoutParams<FlexboxLayoutManager.LayoutParams> {
|
||||||
width = cellSize
|
width = cellSize
|
||||||
height = cellSize
|
height = cellSize
|
||||||
setMargins(2.dp, 2.dp, 2.dp, 2.dp)
|
setMargins(2.dp, 2.dp, 2.dp, 2.dp)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.shuwei.dish.match.adapter
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding
|
import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,7 +12,7 @@ import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding
|
|||||||
* 用于 SubmitFoodActivity 展示各调料槽位的实时用量
|
* 用于 SubmitFoodActivity 展示各调料槽位的实时用量
|
||||||
* 同名调料已在外部聚合,adapter 按 goodsName 作为唯一标识
|
* 同名调料已在外部聚合,adapter 按 goodsName 作为唯一标识
|
||||||
*/
|
*/
|
||||||
class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>() {
|
class SeasoningWeightAdapter : BaseQuickAdapter<SeasoningWeightAdapter.Item, SeasoningWeightAdapter.VH>() {
|
||||||
|
|
||||||
/** 调料展示数据项,key = goodsName(同名调料已聚合) */
|
/** 调料展示数据项,key = goodsName(同名调料已聚合) */
|
||||||
data class Item(
|
data class Item(
|
||||||
@@ -20,19 +22,15 @@ class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>()
|
|||||||
val useWeight: Double
|
val useWeight: Double
|
||||||
)
|
)
|
||||||
|
|
||||||
val items = mutableListOf<Item>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新单个 item,按 goodsName 匹配;不存在则追加
|
* 更新单个 item,按 goodsName 匹配;不存在则追加
|
||||||
*/
|
*/
|
||||||
fun updateItem(item: Item) {
|
fun updateItem(item: Item) {
|
||||||
val idx = items.indexOfFirst { it.goodsName == item.goodsName }
|
val idx = items.indexOfFirst { it.goodsName == item.goodsName }
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
items[idx] = item
|
set(idx, item)
|
||||||
notifyItemChanged(idx)
|
|
||||||
} else {
|
} else {
|
||||||
items.add(item)
|
add(item)
|
||||||
notifyItemInserted(items.lastIndex)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,29 +39,20 @@ class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>()
|
|||||||
*/
|
*/
|
||||||
fun removeItem(goodsName: String) {
|
fun removeItem(goodsName: String) {
|
||||||
val idx = items.indexOfFirst { it.goodsName == goodsName }
|
val idx = items.indexOfFirst { it.goodsName == goodsName }
|
||||||
if (idx >= 0) {
|
if (idx >= 0) removeAt(idx)
|
||||||
items.removeAt(idx)
|
|
||||||
notifyItemRemoved(idx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
val binding = ItemSeasoningWeightBinding.inflate(
|
val binding = ItemSeasoningWeightBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
LayoutInflater.from(parent.context), parent, false
|
|
||||||
)
|
|
||||||
return VH(binding)
|
return VH(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
override fun onBindViewHolder(holder: VH, position: Int, item: Item?) {
|
||||||
holder.bind(items[position])
|
item ?: return
|
||||||
|
holder.binding.tvSeasoningName.text = item.goodsName
|
||||||
|
holder.binding.tvSeasoningWeight.text = "${item.useWeight}g"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = items.size
|
inner class VH(var binding: ItemSeasoningWeightBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
class VH(private val b: ItemSeasoningWeightBinding) : RecyclerView.ViewHolder(b.root) {
|
|
||||||
fun bind(item: Item) {
|
|
||||||
b.tvSeasoningName.text = item.goodsName
|
|
||||||
b.tvSeasoningWeight.text = "${item.useWeight}g"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 返回 Fragment 容器的 View ID,供子类加载 Fragment 使用 */
|
||||||
|
protected fun getFragmentContainerId(): Int = R.id.flContainer
|
||||||
|
|
||||||
override fun setContentView(view: View?) {
|
override fun setContentView(view: View?) {
|
||||||
if (view == binding.root) {
|
if (view == binding.root) {
|
||||||
super.setContentView(view)
|
super.setContentView(view)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.shuwei.dish.match.db
|
|||||||
|
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
import com.shuwei.dish.match.db.dao.AppDao
|
import com.shuwei.dish.match.db.dao.AppDao
|
||||||
|
import com.shuwei.dish.match.db.dao.SeasoningSlotDao
|
||||||
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
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.entity.SeasoningEntity
|
||||||
@@ -9,7 +10,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
class AppRepository(val appDao: AppDao) {
|
class AppRepository(val appDao: AppDao, val seasoningSlotDao: SeasoningSlotDao) {
|
||||||
|
|
||||||
suspend fun insertCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
suspend fun insertCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
||||||
appDao.insertCookFood(item)
|
appDao.insertCookFood(item)
|
||||||
@@ -105,6 +106,15 @@ class AppRepository(val appDao: AppDao) {
|
|||||||
suspend fun insertSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
suspend fun insertSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
||||||
appDao.insertSeasoning(item)
|
appDao.insertSeasoning(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备是否已配置调料槽位
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @return true 表示已有配置,false 表示未配置
|
||||||
|
*/
|
||||||
|
suspend fun hasSeasoningSlotConfig(deviceId: String) = withContext(Dispatchers.IO) {
|
||||||
|
seasoningSlotDao.queryByDeviceId(deviceId).isNotEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
//class SeasoningRepository(val seasoningDao: SeasoningDao) {
|
//class SeasoningRepository(val seasoningDao: SeasoningDao) {
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ open class CommonDialog(
|
|||||||
private var contentText: String? = null
|
private var contentText: String? = null
|
||||||
private var negativeText = "取消"
|
private var negativeText = "取消"
|
||||||
private var positiveText = "确认"
|
private var positiveText = "确认"
|
||||||
|
private var neutralText: String? = null
|
||||||
private var negativeClick: (() -> Unit)? = null
|
private var negativeClick: (() -> Unit)? = null
|
||||||
private var positiveClick: (() -> Unit)? = null
|
private var positiveClick: (() -> Unit)? = null
|
||||||
|
private var neutralClick: (() -> Unit)? = null
|
||||||
private var dismissCallback: (() -> Unit)? = null
|
private var dismissCallback: (() -> Unit)? = null
|
||||||
|
|
||||||
/** 设置标题,为空时隐藏 */
|
/** 设置标题,为空时隐藏 */
|
||||||
@@ -36,18 +38,24 @@ open class CommonDialog(
|
|||||||
/** 设置内容,为空时隐藏 */
|
/** 设置内容,为空时隐藏 */
|
||||||
fun setContent(text: String): CommonDialog = apply { contentText = text }
|
fun setContent(text: String): CommonDialog = apply { contentText = text }
|
||||||
|
|
||||||
/** 设置左侧取消按钮文字及点击回调 */
|
/** 设置左侧取消按钮文字及点击回调(3按钮模式下对应顶部按钮) */
|
||||||
fun setNegativeButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
fun setNegativeButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
||||||
negativeText = text
|
negativeText = text
|
||||||
negativeClick = onClick
|
negativeClick = onClick
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 设置右侧确认按钮文字及点击回调 */
|
/** 设置右侧确认按钮文字及点击回调(3按钮模式下对应底部按钮) */
|
||||||
fun setPositiveButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
fun setPositiveButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
||||||
positiveText = text
|
positiveText = text
|
||||||
positiveClick = onClick
|
positiveClick = onClick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 设置中间第三个按钮文字及点击回调,调用后自动切换为垂直3按钮布局 */
|
||||||
|
fun setNeutralButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
||||||
|
neutralText = text
|
||||||
|
neutralClick = onClick
|
||||||
|
}
|
||||||
|
|
||||||
/** 设置弹窗消失回调 */
|
/** 设置弹窗消失回调 */
|
||||||
fun setOnDismissCallback(callback: () -> Unit): CommonDialog = apply {
|
fun setOnDismissCallback(callback: () -> Unit): CommonDialog = apply {
|
||||||
dismissCallback = callback
|
dismissCallback = callback
|
||||||
@@ -70,6 +78,8 @@ open class CommonDialog(
|
|||||||
val verticalMargin = if (GlobalData.deviceRole == DeviceRole.MASTER) 35.dp else 20.dp
|
val verticalMargin = if (GlobalData.deviceRole == DeviceRole.MASTER) 35.dp else 20.dp
|
||||||
binding.tvTitle.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = verticalMargin }
|
binding.tvTitle.updateLayoutParams<LinearLayout.LayoutParams> { topMargin = verticalMargin }
|
||||||
binding.tvContent.updateLayoutParams<LinearLayout.LayoutParams> { bottomMargin = verticalMargin }
|
binding.tvContent.updateLayoutParams<LinearLayout.LayoutParams> { bottomMargin = verticalMargin }
|
||||||
|
|
||||||
|
// 2按钮点击事件
|
||||||
binding.btnLeft.setOnClickListener {
|
binding.btnLeft.setOnClickListener {
|
||||||
negativeClick?.invoke()
|
negativeClick?.invoke()
|
||||||
dismiss()
|
dismiss()
|
||||||
@@ -78,6 +88,21 @@ open class CommonDialog(
|
|||||||
positiveClick?.invoke()
|
positiveClick?.invoke()
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3按钮点击事件(negativeClick/positiveClick 与2按钮模式共用)
|
||||||
|
binding.btnTop.setOnClickListener {
|
||||||
|
negativeClick?.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
binding.btnMiddle.setOnClickListener {
|
||||||
|
neutralClick?.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
binding.btnBottom.setOnClickListener {
|
||||||
|
positiveClick?.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
setOnDismissListener { dismissCallback?.invoke() }
|
setOnDismissListener { dismissCallback?.invoke() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,8 +112,21 @@ open class CommonDialog(
|
|||||||
binding.tvContent.text = contentText
|
binding.tvContent.text = contentText
|
||||||
binding.tvTitle.visibility = if (titleText.isNullOrEmpty()) View.GONE else View.VISIBLE
|
binding.tvTitle.visibility = if (titleText.isNullOrEmpty()) View.GONE else View.VISIBLE
|
||||||
binding.tvContent.visibility = if (contentText.isNullOrEmpty()) View.GONE else View.VISIBLE
|
binding.tvContent.visibility = if (contentText.isNullOrEmpty()) View.GONE else View.VISIBLE
|
||||||
binding.btnLeft.text = negativeText
|
|
||||||
binding.btnRight.text = positiveText
|
val hasThreeButtons = !neutralText.isNullOrEmpty()
|
||||||
|
binding.layoutButtonsHorizontal.visibility = if (hasThreeButtons) View.GONE else View.VISIBLE
|
||||||
|
binding.layoutButtonsVertical.visibility = if (hasThreeButtons) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
if (hasThreeButtons) {
|
||||||
|
// 3按钮模式:顶部=取消,中间=中立,底部=确认
|
||||||
|
binding.btnTop.text = negativeText
|
||||||
|
binding.btnMiddle.text = neutralText
|
||||||
|
binding.btnBottom.text = positiveText
|
||||||
|
} else {
|
||||||
|
// 2按钮模式
|
||||||
|
binding.btnLeft.text = negativeText
|
||||||
|
binding.btnRight.text = positiveText
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import java.net.UnknownHostException
|
|||||||
* @param onSuccess 成功回调
|
* @param onSuccess 成功回调
|
||||||
* @param onFailure 自定义错误回调(可选,不传则用默认提示)
|
* @param onFailure 自定义错误回调(可选,不传则用默认提示)
|
||||||
*/
|
*/
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
suspend fun <T> request(
|
suspend fun <T> request(
|
||||||
onRequest: suspend () -> ApiResponse<T>,
|
onRequest: suspend () -> ApiResponse<T>,
|
||||||
onSuccess: (T) -> Unit,
|
onSuccess: (T) -> Unit,
|
||||||
@@ -73,6 +74,7 @@ data class CodeMsg(
|
|||||||
var msg: String? = null
|
var msg: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
fun getApiException(e: Exception): ApiException {
|
fun getApiException(e: Exception): ApiException {
|
||||||
// 捕获各类网络异常并转换为自定义异常
|
// 捕获各类网络异常并转换为自定义异常
|
||||||
return when (e) {
|
return when (e) {
|
||||||
@@ -116,7 +118,7 @@ fun httpException2ApiException(e: HttpException): ApiException {
|
|||||||
val body = e.response()?.errorBody()?.string()
|
val body = e.response()?.errorBody()?.string()
|
||||||
val codeMsg: CodeMsg? = try {
|
val codeMsg: CodeMsg? = try {
|
||||||
body?.toObject<CodeMsg>()
|
body?.toObject<CodeMsg>()
|
||||||
} catch (ex: Exception) {
|
} catch (_: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
return ApiException(
|
return ApiException(
|
||||||
|
|||||||
@@ -8,104 +8,89 @@ import com.shuwei.dish.match.entity.FoodRecord
|
|||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.entity.SeasoningEntity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class NetViewModel : ViewModel() {
|
/**
|
||||||
|
* 网络请求 ViewModel,所有网络操作通过 RemoteRepository 发起,不直接依赖 apiService
|
||||||
|
* @param repository 网络数据仓库,默认使用单例实例
|
||||||
|
*/
|
||||||
|
class NetViewModel(
|
||||||
|
private val repository: RemoteRepository = RemoteRepository()
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交制作菜品
|
||||||
|
*/
|
||||||
fun submitCookFood(
|
fun submitCookFood(
|
||||||
entity: CookFoodEntity,
|
entity: CookFoodEntity,
|
||||||
onSuccess: (Any?) -> Unit,
|
onSuccess: (Any?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.submitCookFood(entity, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.submitCookFood(param = entity)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品详情
|
||||||
|
*/
|
||||||
fun getFoodDetail(
|
fun getFoodDetail(
|
||||||
foodId: String,
|
foodId: String,
|
||||||
onSuccess: (CookFoodEntity?) -> Unit,
|
onSuccess: (CookFoodEntity?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.getFoodDetail(foodId, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.getFoodDetail(foodId = foodId)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品列表
|
||||||
|
*/
|
||||||
fun searchFoodList(
|
fun searchFoodList(
|
||||||
param: MutableMap<String, Any>,
|
param: MutableMap<String, Any>,
|
||||||
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.searchFoodList(param, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.searchFoodList(param = param)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询采样数据列表
|
||||||
|
*/
|
||||||
fun getSamplingList(
|
fun getSamplingList(
|
||||||
param: MutableMap<String, Any>,
|
param: MutableMap<String, Any>,
|
||||||
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.getSamplingList(param, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.getSamplingList(param = param)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询物品信息列表
|
||||||
|
*/
|
||||||
fun queryGoodsList(
|
fun queryGoodsList(
|
||||||
param: MutableMap<String, Any>,
|
param: MutableMap<String, Any>,
|
||||||
onSuccess: (MutableList<CookFoodGoodsEntity>?) -> Unit,
|
onSuccess: (MutableList<CookFoodGoodsEntity>?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.queryGoodsList(param, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.queryGoodsList(param = param)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询调料信息列表
|
||||||
|
*/
|
||||||
fun querySeasoningList(
|
fun querySeasoningList(
|
||||||
param: MutableMap<String, Any>,
|
param: MutableMap<String, Any>,
|
||||||
onSuccess: (MutableList<SeasoningEntity>?) -> Unit,
|
onSuccess: (MutableList<SeasoningEntity>?) -> Unit,
|
||||||
onFailure: (String, String) -> Unit
|
onFailure: (String, String) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
request(
|
repository.querySeasoningList(param, onSuccess, onFailure)
|
||||||
onRequest = {
|
|
||||||
apiService.querySeasoningList(param = param)
|
|
||||||
},
|
|
||||||
onSuccess = onSuccess,
|
|
||||||
onFailure = onFailure
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.entity.FoodRecord
|
||||||
|
import com.shuwei.dish.match.entity.SeasoningEntity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络数据仓库,封装所有 ApiService 调用
|
||||||
|
* ViewModel 不直接接触 apiService,统一通过此类发起网络请求
|
||||||
|
*/
|
||||||
|
class RemoteRepository {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交制作菜品
|
||||||
|
* @param entity 菜品实体
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun submitCookFood(
|
||||||
|
entity: CookFoodEntity,
|
||||||
|
onSuccess: (Any?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.submitCookFood(param = entity) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品详情
|
||||||
|
* @param foodId 菜品 ID
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun getFoodDetail(
|
||||||
|
foodId: String,
|
||||||
|
onSuccess: (CookFoodEntity?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.getFoodDetail(foodId = foodId) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品列表
|
||||||
|
* @param param 查询参数
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun searchFoodList(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.searchFoodList(param = param) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询采样数据列表
|
||||||
|
* @param param 查询参数
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun getSamplingList(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onSuccess: (MutableList<FoodRecord>?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.getSamplingList(param = param) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询物品信息列表
|
||||||
|
* @param param 查询参数
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun queryGoodsList(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onSuccess: (MutableList<CookFoodGoodsEntity>?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.queryGoodsList(param = param) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询调料信息列表
|
||||||
|
* @param param 查询参数
|
||||||
|
* @param onSuccess 成功回调
|
||||||
|
* @param onFailure 失败回调,参数为 (errorCode, errorMsg)
|
||||||
|
*/
|
||||||
|
suspend fun querySeasoningList(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onSuccess: (MutableList<SeasoningEntity>?) -> Unit,
|
||||||
|
onFailure: (String, String) -> Unit
|
||||||
|
) = request(
|
||||||
|
onRequest = { apiService.querySeasoningList(param = param) },
|
||||||
|
onSuccess = onSuccess,
|
||||||
|
onFailure = onFailure
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -102,7 +102,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory =
|
val factory =
|
||||||
AppFactory(AppRepository(db.appDao()))
|
AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel =
|
appViewModel =
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class HomeActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
val factory = AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class InitActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
val factory = AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.shuwei.dish.match.scale.ScaleServiceManager
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import com.shuwei.dish.match.utils.NetworkUtil
|
import com.shuwei.dish.match.utils.NetworkUtil
|
||||||
|
import com.shuwei.dish.match.utils.SizeTool
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
@@ -51,7 +52,7 @@ private const val VIEW_TYPE_SCALE1 = 3
|
|||||||
class MasterScaleActivity : BaseActivity() {
|
class MasterScaleActivity : BaseActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityMasterScaleBinding
|
private lateinit var binding: ActivityMasterScaleBinding
|
||||||
|
private val size by lazy { SizeTool.getFlexLayoutSize(10.dp) }
|
||||||
private data class DeviceGroup(
|
private data class DeviceGroup(
|
||||||
val deviceId: String,
|
val deviceId: String,
|
||||||
val ip: String,
|
val ip: String,
|
||||||
@@ -357,12 +358,7 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
b.tvDeviceLabel.text = "设备:${group.deviceId}"
|
b.tvDeviceLabel.text = "设备:${group.deviceId}"
|
||||||
|
|
||||||
if (innerAdapter == null) {
|
if (innerAdapter == null) {
|
||||||
val screenWidth = resources.displayMetrics.widthPixels
|
b.rvScales.layoutParams = b.rvScales.layoutParams.also { it.height = size.rvHeight }
|
||||||
val usable = screenWidth - 8 * 4.dp - 10.dp
|
|
||||||
val smallSize = usable / 9
|
|
||||||
val largeSize = (usable - smallSize * 6) / 2
|
|
||||||
val rvHeight = smallSize * 3 + 3 * 4.dp
|
|
||||||
b.rvScales.layoutParams = b.rvScales.layoutParams.also { it.height = rvHeight }
|
|
||||||
b.rvScales.layoutManager = FlexboxLayoutManager(b.root.context).apply {
|
b.rvScales.layoutManager = FlexboxLayoutManager(b.root.context).apply {
|
||||||
flexDirection = FlexDirection.COLUMN
|
flexDirection = FlexDirection.COLUMN
|
||||||
flexWrap = FlexWrap.WRAP
|
flexWrap = FlexWrap.WRAP
|
||||||
@@ -370,8 +366,8 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
b.rvScales.itemAnimator = null
|
b.rvScales.itemAnimator = null
|
||||||
innerAdapter = Seasoning22GridAdapter(
|
innerAdapter = Seasoning22GridAdapter(
|
||||||
largeSize,
|
size.largeSize,
|
||||||
smallSize,
|
size.smallSize,
|
||||||
showNameOnly = false,
|
showNameOnly = false,
|
||||||
showAddress = true
|
showAddress = true
|
||||||
).apply {
|
).apply {
|
||||||
@@ -455,6 +451,7 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
val scale = scales.firstOrNull()
|
val scale = scales.firstOrNull()
|
||||||
b.llScaleContainer.tag = scale
|
b.llScaleContainer.tag = scale
|
||||||
b.tvAddr.text = scale?.let { "秤 ${it.address}" } ?: ""
|
b.tvAddr.text = scale?.let { "秤 ${it.address}" } ?: ""
|
||||||
|
b.tvName.text = scale?.name?.takeIf { it.isNotBlank() } ?: "-"
|
||||||
b.tvWeight.text = scale?.let { "${it.weight} g" } ?: ""
|
b.tvWeight.text = scale?.let { "${it.weight} g" } ?: ""
|
||||||
b.tvState.text = stateStr(scale?.state)
|
b.tvState.text = stateStr(scale?.state)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
val factory = AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
val factory = AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,33 +2,20 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Color
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.ViewGroup
|
import android.provider.Settings
|
||||||
import androidx.appcompat.widget.AppCompatButton
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.toColorInt
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.camera.view.PreviewView
|
|
||||||
import androidx.core.view.updateLayoutParams
|
|
||||||
import com.shuwei.dish.match.R
|
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.base.DeviceRole
|
|
||||||
import com.shuwei.dish.match.base.GlobalData
|
|
||||||
import com.shuwei.dish.match.databinding.ActivitySettingBinding
|
import com.shuwei.dish.match.databinding.ActivitySettingBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
import com.shuwei.dish.match.ui.fragment.CollectFragment
|
|
||||||
import com.shuwei.dish.match.ui.fragment.DeviceConfigFragment
|
|
||||||
import com.shuwei.dish.match.ui.fragment.SeasoningConfigFragment
|
|
||||||
import com.shuwei.dish.match.utils.CameraUtils
|
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,10 +29,10 @@ class SettingActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivitySettingBinding
|
private lateinit var binding: ActivitySettingBinding
|
||||||
private val cameraUtils: CameraUtils by lazy {
|
// private val cameraUtils: CameraUtils by lazy {
|
||||||
CameraUtils(this)
|
// CameraUtils(this)
|
||||||
}
|
// }
|
||||||
private lateinit var previewView: PreviewView
|
// private lateinit var previewView: PreviewView
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -55,104 +42,54 @@ class SettingActivity : BaseActivity() {
|
|||||||
setTitleBar(titleBarAction = {
|
setTitleBar(titleBarAction = {
|
||||||
it.visible()
|
it.visible()
|
||||||
}, titleAction = {
|
}, titleAction = {
|
||||||
it.text = "设置"
|
it.text = "设备设置"
|
||||||
}, rightIconActon = {
|
}, rightIconActon = {
|
||||||
it.gone()
|
it.visible()
|
||||||
})
|
it.clickWithDebounce {
|
||||||
|
|
||||||
// 默认显示设备配置Fragment
|
|
||||||
if (savedInstanceState == null) {
|
|
||||||
showDeviceConfigFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
initUI()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化UI和事件监听
|
|
||||||
*/
|
|
||||||
private fun initUI() {
|
|
||||||
// 设备配置按钮点击事件
|
|
||||||
binding.btnDeviceConfig.setOnClickListener {
|
|
||||||
showDeviceConfigFragment()
|
|
||||||
|
|
||||||
loadTabStyle(button = binding.btnDeviceConfig, isSelected = true)
|
|
||||||
loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
|
||||||
loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调料配置按钮点击事件
|
|
||||||
binding.btnSeasoningConfig.setOnClickListener {
|
|
||||||
showSeasoningConfigFragment()
|
|
||||||
|
|
||||||
loadTabStyle(button = binding.btnDeviceConfig, isSelected = false)
|
|
||||||
loadTabStyle(button = binding.btnSeasoningConfig, isSelected = true)
|
|
||||||
loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 菜品采集按钮点击事件
|
|
||||||
binding.btnFoodCollect.setOnClickListener {
|
|
||||||
checkCameraPermissionAndShowFragment()
|
|
||||||
|
|
||||||
loadTabStyle(button = binding.btnDeviceConfig, isSelected = false)
|
|
||||||
loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
|
||||||
loadTabStyle(button = binding.btnFoodCollect, isSelected = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主设备显示「秤数据监控」入口
|
|
||||||
if (GlobalData.deviceRole == DeviceRole.MASTER) {
|
|
||||||
binding.btnScaleMonitor.visible()
|
|
||||||
binding.btnScaleMonitor.setOnClickListener {
|
|
||||||
startActivity<MasterScaleActivity>()
|
startActivity<MasterScaleActivity>()
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
// 初始化按钮颜色(默认设备配置为选中状态)
|
initView()
|
||||||
|
|
||||||
loadTabStyle(button = binding.btnDeviceConfig, isSelected = true)
|
// // 默认显示设备配置Fragment
|
||||||
loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
// if (savedInstanceState == null) {
|
||||||
loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
// showDeviceConfigFragment()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// initUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
// /** 刷新角色按钮文字 */
|
|
||||||
// private fun updateRoleButtonText() {
|
|
||||||
// val roleLabel = if (GlobalData.deviceRole == DeviceRole.MASTER) "主设备" else "子设备"
|
|
||||||
// binding.btnDeviceRole.text = "设备角色:$roleLabel"
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
private fun initView() {
|
||||||
* 加载顶部Tab按钮样式
|
binding.tvCurrentMode.text = when (SpTool.cookMode) {
|
||||||
*
|
0 -> "当前:制作模式"
|
||||||
* @param button 按钮
|
1 -> "当前:采样模式"
|
||||||
* @param isSelected 是否选中
|
else -> "当前:未知模式"
|
||||||
*/
|
|
||||||
private fun loadTabStyle(button: AppCompatButton, isSelected: Boolean) {
|
|
||||||
button.apply {
|
|
||||||
if (isSelected){
|
|
||||||
// 选中
|
|
||||||
setTextColor(Color.WHITE)
|
|
||||||
textSize = 28f
|
|
||||||
setTypeface(null, android.graphics.Typeface.BOLD)
|
|
||||||
background = ContextCompat.getDrawable(this@SettingActivity, R.drawable.bg_btn_underline)
|
|
||||||
} else {
|
|
||||||
// 未选中
|
|
||||||
setTextColor("#5E7585".toColorInt())
|
|
||||||
textSize = 26f
|
|
||||||
setTypeface(null, android.graphics.Typeface.NORMAL)
|
|
||||||
background = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
binding.llCookMode.clickWithDebounce {
|
||||||
|
SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.COOK_MODE)
|
||||||
|
}
|
||||||
|
binding.llSeasoningConfig.clickWithDebounce {
|
||||||
|
SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.SEASONING_CONFIG)
|
||||||
|
}
|
||||||
|
binding.llFoodCollect.clickWithDebounce {
|
||||||
|
checkCameraPermission()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openCollectPage() {
|
||||||
|
SingleFragmentActivity.start(this, SingleFragmentActivity.PageType.FOOD_COLLECT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查相机权限并显示 CollectFragment
|
* 检查相机权限并显示 CollectFragment
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ObsoleteSdkInt")
|
@SuppressLint("ObsoleteSdkInt")
|
||||||
private fun checkCameraPermissionAndShowFragment() {
|
private fun checkCameraPermission() {
|
||||||
val collectFragment = fragmentList[2]
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
// Android 6.0 以下,直接显示 Fragment
|
// Android 6.0 以下,直接打开
|
||||||
showFragment(collectFragment)
|
openCollectPage()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (ContextCompat.checkSelfPermission(
|
if (ContextCompat.checkSelfPermission(
|
||||||
@@ -160,109 +97,228 @@ class SettingActivity : BaseActivity() {
|
|||||||
Manifest.permission.CAMERA
|
Manifest.permission.CAMERA
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
) {
|
) {
|
||||||
// 权限已授予,直接显示 Fragment
|
// 权限已授予,直接打开
|
||||||
showFragment(collectFragment)
|
openCollectPage()
|
||||||
} else {
|
} else {
|
||||||
// 权限未授予,申请权限
|
// 权限未授予,申请权限
|
||||||
requestPermission(Manifest.permission.CAMERA) { isGranted ->
|
requestPermission(Manifest.permission.CAMERA) { isGranted ->
|
||||||
if (isGranted) {
|
if (isGranted) {
|
||||||
// 权限已授予,显示 CollectFragment
|
// 权限已授予,直接打开
|
||||||
showFragment(collectFragment)
|
openCollectPage()
|
||||||
} else {
|
} else {
|
||||||
// 权限被拒绝
|
// 权限被拒绝
|
||||||
toast("暂无相机权限,无法使用菜品采集功能")
|
showNotGrantedCameraPermissionDialog()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun showNotGrantedCameraPermissionDialog() {
|
||||||
* 初始化相机
|
CommonDialog(this)
|
||||||
* @param container 相机预览容器
|
.setTitle("温馨提示")
|
||||||
*/
|
.setContent("暂无相机权限,无法使用菜品采集功能,请确认是否同意开始权限?")
|
||||||
fun initCamera(container: ViewGroup) {
|
.setNegativeButton("不同意")
|
||||||
cameraUtils.initCamera()
|
.setPositiveButton("同意") {
|
||||||
val previewBinding =
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||||
LayoutCameraPreviewBinding.inflate(layoutInflater, container)
|
data = Uri.fromParts("package", packageName, null)
|
||||||
previewView = previewBinding.previewView.also {
|
|
||||||
it.updateLayoutParams {
|
|
||||||
width = 456.dp
|
|
||||||
height = 342.dp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cameraUtils.setPreviewController(previewView)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activity 恢复时绑定相机
|
|
||||||
*/
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
cameraUtils.bind()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activity 暂停时解绑相机
|
|
||||||
*/
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
cameraUtils.unbind()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 提供给 Fragment 调用的拍照方法
|
|
||||||
*/
|
|
||||||
fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = {}) {
|
|
||||||
cameraUtils.takePhoto(succCallback = succCallback, failCallback = failCallback)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示设备切换Fragment
|
|
||||||
*/
|
|
||||||
private fun showDeviceConfigFragment() {
|
|
||||||
showFragment(fragmentList[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示设调料配置Fragment
|
|
||||||
*/
|
|
||||||
private fun showSeasoningConfigFragment() {
|
|
||||||
showFragment(fragmentList[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
private val fragmentList = mutableListOf<Fragment>().apply {
|
|
||||||
add(DeviceConfigFragment())
|
|
||||||
add(SeasoningConfigFragment())
|
|
||||||
add(CollectFragment())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示指定的 Fragment
|
|
||||||
* 使用 add/show/hide 方式管理 Fragment,避免重复创建
|
|
||||||
* 已添加的 Fragment 直接显示,未添加的 Fragment 先添加再显示
|
|
||||||
*/
|
|
||||||
private fun showFragment(fragment: Fragment) {
|
|
||||||
runCatching {
|
|
||||||
supportFragmentManager.beginTransaction().apply {
|
|
||||||
// 如果 Fragment 还未添加到容器中,则添加
|
|
||||||
if (!fragment.isAdded) {
|
|
||||||
add(binding.fragmentContainer.id, fragment)
|
|
||||||
} else {
|
|
||||||
// 已添加过,直接显示
|
|
||||||
show(fragment)
|
|
||||||
}
|
}
|
||||||
|
startActivity(intent) {
|
||||||
// 隐藏其他 Fragment
|
checkCameraPermission()
|
||||||
fragmentList.forEach { otherFragment ->
|
|
||||||
if (otherFragment != fragment && otherFragment.isAdded) {
|
|
||||||
hide(otherFragment)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
commit()
|
|
||||||
}
|
}
|
||||||
}.onFailure {
|
.show()
|
||||||
it.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 初始化UI和事件监听
|
||||||
|
// */
|
||||||
|
// private fun initUI() {
|
||||||
|
// // 设备配置按钮点击事件
|
||||||
|
// binding.btnDeviceConfig.setOnClickListener {
|
||||||
|
// showDeviceConfigFragment()
|
||||||
|
//
|
||||||
|
// loadTabStyle(button = binding.btnDeviceConfig, isSelected = true)
|
||||||
|
// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
||||||
|
// loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 调料配置按钮点击事件
|
||||||
|
// binding.btnSeasoningConfig.setOnClickListener {
|
||||||
|
// showSeasoningConfigFragment()
|
||||||
|
//
|
||||||
|
// loadTabStyle(button = binding.btnDeviceConfig, isSelected = false)
|
||||||
|
// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = true)
|
||||||
|
// loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 菜品采集按钮点击事件
|
||||||
|
// binding.btnFoodCollect.setOnClickListener {
|
||||||
|
// checkCameraPermissionAndShowFragment()
|
||||||
|
//
|
||||||
|
// loadTabStyle(button = binding.btnDeviceConfig, isSelected = false)
|
||||||
|
// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
||||||
|
// loadTabStyle(button = binding.btnFoodCollect, isSelected = true)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 主设备显示「秤数据监控」入口
|
||||||
|
// if (GlobalData.deviceRole == DeviceRole.MASTER) {
|
||||||
|
// binding.btnScaleMonitor.visible()
|
||||||
|
// binding.btnScaleMonitor.setOnClickListener {
|
||||||
|
// startActivity<MasterScaleActivity>()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 初始化按钮颜色(默认设备配置为选中状态)
|
||||||
|
//
|
||||||
|
// loadTabStyle(button = binding.btnDeviceConfig, isSelected = true)
|
||||||
|
// loadTabStyle(button = binding.btnSeasoningConfig, isSelected = false)
|
||||||
|
// loadTabStyle(button = binding.btnFoodCollect, isSelected = false)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 加载顶部Tab按钮样式
|
||||||
|
// *
|
||||||
|
// * @param button 按钮
|
||||||
|
// * @param isSelected 是否选中
|
||||||
|
// */
|
||||||
|
// private fun loadTabStyle(button: AppCompatButton, isSelected: Boolean) {
|
||||||
|
// button.apply {
|
||||||
|
// if (isSelected){
|
||||||
|
// // 选中
|
||||||
|
// setTextColor(Color.WHITE)
|
||||||
|
// textSize = 28f
|
||||||
|
// setTypeface(null, android.graphics.Typeface.BOLD)
|
||||||
|
// background = ContextCompat.getDrawable(this@SettingActivity, R.drawable.bg_btn_underline)
|
||||||
|
// } else {
|
||||||
|
// // 未选中
|
||||||
|
// setTextColor("#5E7585".toColorInt())
|
||||||
|
// textSize = 26f
|
||||||
|
// setTypeface(null, android.graphics.Typeface.NORMAL)
|
||||||
|
// background = null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 检查相机权限并显示 CollectFragment
|
||||||
|
// */
|
||||||
|
// @SuppressLint("ObsoleteSdkInt")
|
||||||
|
// private fun checkCameraPermissionAndShowFragment() {
|
||||||
|
// val collectFragment = fragmentList[2]
|
||||||
|
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
|
// // Android 6.0 以下,直接显示 Fragment
|
||||||
|
// showFragment(collectFragment)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// if (ContextCompat.checkSelfPermission(
|
||||||
|
// this,
|
||||||
|
// Manifest.permission.CAMERA
|
||||||
|
// ) == PackageManager.PERMISSION_GRANTED
|
||||||
|
// ) {
|
||||||
|
// // 权限已授予,直接显示 Fragment
|
||||||
|
// showFragment(collectFragment)
|
||||||
|
// } else {
|
||||||
|
// // 权限未授予,申请权限
|
||||||
|
// requestPermission(Manifest.permission.CAMERA) { isGranted ->
|
||||||
|
// if (isGranted) {
|
||||||
|
// // 权限已授予,显示 CollectFragment
|
||||||
|
// showFragment(collectFragment)
|
||||||
|
// } else {
|
||||||
|
// // 权限被拒绝
|
||||||
|
// toast("暂无相机权限,无法使用菜品采集功能")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 初始化相机
|
||||||
|
// * @param container 相机预览容器
|
||||||
|
// */
|
||||||
|
// fun initCamera(container: ViewGroup) {
|
||||||
|
// cameraUtils.initCamera()
|
||||||
|
// val previewBinding =
|
||||||
|
// LayoutCameraPreviewBinding.inflate(layoutInflater, container)
|
||||||
|
// previewView = previewBinding.previewView.also {
|
||||||
|
// it.updateLayoutParams {
|
||||||
|
// width = 456.dp
|
||||||
|
// height = 342.dp
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// cameraUtils.setPreviewController(previewView)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Activity 恢复时绑定相机
|
||||||
|
// */
|
||||||
|
// override fun onResume() {
|
||||||
|
// super.onResume()
|
||||||
|
// cameraUtils.bind()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Activity 暂停时解绑相机
|
||||||
|
// */
|
||||||
|
// override fun onPause() {
|
||||||
|
// super.onPause()
|
||||||
|
// cameraUtils.unbind()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 提供给 Fragment 调用的拍照方法
|
||||||
|
// */
|
||||||
|
// fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = {}) {
|
||||||
|
// cameraUtils.takePhoto(succCallback = succCallback, failCallback = failCallback)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 显示设备切换Fragment
|
||||||
|
// */
|
||||||
|
// private fun showDeviceConfigFragment() {
|
||||||
|
// showFragment(fragmentList[0])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 显示设调料配置Fragment
|
||||||
|
// */
|
||||||
|
// private fun showSeasoningConfigFragment() {
|
||||||
|
// showFragment(fragmentList[1])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private val fragmentList = mutableListOf<Fragment>().apply {
|
||||||
|
// add(DeviceConfigFragment())
|
||||||
|
// add(SeasoningConfigFragment())
|
||||||
|
// add(CollectFragment())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 显示指定的 Fragment
|
||||||
|
// * 使用 add/show/hide 方式管理 Fragment,避免重复创建
|
||||||
|
// * 已添加的 Fragment 直接显示,未添加的 Fragment 先添加再显示
|
||||||
|
// */
|
||||||
|
// private fun showFragment(fragment: Fragment) {
|
||||||
|
// runCatching {
|
||||||
|
// supportFragmentManager.beginTransaction().apply {
|
||||||
|
// // 如果 Fragment 还未添加到容器中,则添加
|
||||||
|
// if (!fragment.isAdded) {
|
||||||
|
// add(binding.fragmentContainer.id, fragment)
|
||||||
|
// } else {
|
||||||
|
// // 已添加过,直接显示
|
||||||
|
// show(fragment)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 隐藏其他 Fragment
|
||||||
|
// fragmentList.forEach { otherFragment ->
|
||||||
|
// if (otherFragment != fragment && otherFragment.isAdded) {
|
||||||
|
// hide(otherFragment)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// commit()
|
||||||
|
// }
|
||||||
|
// }.onFailure {
|
||||||
|
// it.printStackTrace()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.ui.fragment.CollectFragment
|
||||||
|
import com.shuwei.dish.match.ui.fragment.DeviceConfigFragment
|
||||||
|
import com.shuwei.dish.match.ui.fragment.SeasoningConfigFragment
|
||||||
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用单 Fragment 容器 Activity
|
||||||
|
* 通过 [PageType] 决定加载哪个 Fragment,避免为每个配置/功能页面单独创建 Activity
|
||||||
|
*/
|
||||||
|
class SingleFragmentActivity : BaseActivity() {
|
||||||
|
|
||||||
|
interface LifecycleCallback {
|
||||||
|
fun onActivityResume()
|
||||||
|
fun onActivityPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持的页面类型枚举
|
||||||
|
* 新增页面时在此追加枚举值,并在 [createFragment] 中补充对应分支
|
||||||
|
*/
|
||||||
|
enum class PageType {
|
||||||
|
/** 菜品采集页 */
|
||||||
|
FOOD_COLLECT,
|
||||||
|
|
||||||
|
/** 设备配置页 */
|
||||||
|
COOK_MODE,
|
||||||
|
|
||||||
|
/** 调料配置页 */
|
||||||
|
SEASONING_CONFIG,
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXTRA_PAGE_TYPE = "extra_page_type"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动 SingleFragmentActivity
|
||||||
|
* @param context 调用方 Context
|
||||||
|
* @param pageType 要显示的页面类型
|
||||||
|
*/
|
||||||
|
fun start(context: Context, pageType: PageType) {
|
||||||
|
Intent(context, SingleFragmentActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_PAGE_TYPE, pageType.name)
|
||||||
|
context.startActivity(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var lifecycleCallback: LifecycleCallback? = null
|
||||||
|
fun setLifecycleCallback(callback: LifecycleCallback) {
|
||||||
|
lifecycleCallback = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setHeaderBackground()
|
||||||
|
|
||||||
|
// 解析页面类型,非法值直接关闭
|
||||||
|
val typeName = intent.getStringExtra(EXTRA_PAGE_TYPE)
|
||||||
|
val pageType = typeName?.let {
|
||||||
|
runCatching { PageType.valueOf(it) }.getOrNull()
|
||||||
|
}
|
||||||
|
if (pageType == null) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置标题栏
|
||||||
|
setTitleBar(
|
||||||
|
titleBarAction = { it.visible() },
|
||||||
|
titleAction = { it.text = getTitleForPage(pageType) },
|
||||||
|
rightIconActon = { it.gone() }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 首次创建时加载 Fragment,避免屏幕旋转重复添加
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
val fragment = createFragment(pageType)
|
||||||
|
supportFragmentManager.beginTransaction()
|
||||||
|
.replace(getFragmentContainerId(), fragment)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据页面类型返回对应标题文本
|
||||||
|
*/
|
||||||
|
private fun getTitleForPage(pageType: PageType): String = when (pageType) {
|
||||||
|
PageType.FOOD_COLLECT -> "食材采样"
|
||||||
|
PageType.COOK_MODE -> "餐品模式"
|
||||||
|
PageType.SEASONING_CONFIG -> "调料区设置"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据页面类型创建对应 Fragment 实例
|
||||||
|
*/
|
||||||
|
private fun createFragment(pageType: PageType): Fragment = when (pageType) {
|
||||||
|
PageType.FOOD_COLLECT -> CollectFragment()
|
||||||
|
PageType.COOK_MODE -> DeviceConfigFragment()
|
||||||
|
PageType.SEASONING_CONFIG -> SeasoningConfigFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
lifecycleCallback?.onActivityResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
lifecycleCallback?.onActivityPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import com.shuwei.dish.match.scale.ScaleData
|
|||||||
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
||||||
import com.shuwei.dish.match.scale.ScaleServiceManager
|
import com.shuwei.dish.match.scale.ScaleServiceManager
|
||||||
import com.shuwei.dish.match.utils.NetworkUtil
|
import com.shuwei.dish.match.utils.NetworkUtil
|
||||||
|
import com.shuwei.dish.match.utils.SizeTool
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -61,6 +62,7 @@ class SlaveActivity : BaseActivity() {
|
|||||||
private val mainHandler = Handler(Looper.getMainLooper())
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
/** 当前高亮清除任务,新高亮触发时取消旧任务 */
|
/** 当前高亮清除任务,新高亮触发时取消旧任务 */
|
||||||
private var clearHighlightRunnable: Runnable? = null
|
private var clearHighlightRunnable: Runnable? = null
|
||||||
|
private val size by lazy { SizeTool.getFlexLayoutSize(10.dp) }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -90,13 +92,8 @@ class SlaveActivity : BaseActivity() {
|
|||||||
binding.rvScaleList.itemAnimator = null
|
binding.rvScaleList.itemAnimator = null
|
||||||
when (GlobalData.deviceId) {
|
when (GlobalData.deviceId) {
|
||||||
ScaleDeviceConfig.DEVICE_ID_22 -> {
|
ScaleDeviceConfig.DEVICE_ID_22 -> {
|
||||||
val screenWidth = resources.displayMetrics.widthPixels
|
|
||||||
val usable = screenWidth - 8 * 4.dp - 10.dp
|
|
||||||
val smallSize = usable / 9
|
|
||||||
val largeSize = (usable - smallSize * 6) / 2
|
|
||||||
val rvHeight = smallSize * 3 + 3 * 4.dp
|
|
||||||
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> {
|
binding.rvScaleList.updateLayoutParams<LinearLayout.LayoutParams> {
|
||||||
height = rvHeight
|
height = size.rvHeight
|
||||||
weight = 0f
|
weight = 0f
|
||||||
topMargin = 20.dp
|
topMargin = 20.dp
|
||||||
}
|
}
|
||||||
@@ -105,7 +102,7 @@ class SlaveActivity : BaseActivity() {
|
|||||||
flexWrap = FlexWrap.WRAP
|
flexWrap = FlexWrap.WRAP
|
||||||
alignItems = AlignItems.FLEX_START
|
alignItems = AlignItems.FLEX_START
|
||||||
}
|
}
|
||||||
scale22Adapter = Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = false).also {
|
scale22Adapter = Seasoning22GridAdapter(size.largeSize, size.smallSize, showNameOnly = false).also {
|
||||||
it.onItemClick = { scale, _ -> showTareDialog(scale.address) }
|
it.onItemClick = { scale, _ -> showTareDialog(scale.address) }
|
||||||
}
|
}
|
||||||
binding.rvScaleList.adapter = scale22Adapter
|
binding.rvScaleList.adapter = scale22Adapter
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.shuwei.dish.match.ui
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@@ -13,6 +14,7 @@ import com.shuwei.dish.match.base.BaseActivity
|
|||||||
import com.shuwei.dish.match.base.BaseApp
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
import com.shuwei.dish.match.databinding.ActivitySubmitFoodBinding
|
import com.shuwei.dish.match.databinding.ActivitySubmitFoodBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
import com.shuwei.dish.match.db.AppRepository
|
||||||
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
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
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.entity.FoodRecord
|
||||||
@@ -23,6 +25,7 @@ import com.shuwei.dish.match.utils.AddressUtil
|
|||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
|
||||||
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||||
@@ -83,6 +86,12 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private val rawWeightMap = mutableMapOf<String, Triple<String, String, Double>>()
|
private val rawWeightMap = mutableMapOf<String, Triple<String, String, Double>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isCooking=true 时从 goodsList 预填充的历史用量,key = goodsName,value = goodsId to useWeight
|
||||||
|
* 用于 refreshAdapterByName 时叠加到秤新增用量上
|
||||||
|
*/
|
||||||
|
private val baseSeasoningMap = mutableMapOf<String, Pair<String, Double>>()
|
||||||
|
|
||||||
@Suppress("unchecked_cast", "DEPRECATION")
|
@Suppress("unchecked_cast", "DEPRECATION")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -93,8 +102,11 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
intent.extras?.apply {
|
intent.extras?.apply {
|
||||||
food = getSerializable(FOOD_ITEM) as FoodRecord?
|
food = getSerializable(FOOD_ITEM) as FoodRecord?
|
||||||
Log.d(TAG, "onCreate: cookMode=${food?.cookMode}")
|
Log.d(TAG, "onCreate: cookMode=${food?.cookMode}")
|
||||||
// 非烹饪中,从菜品主辅材配置页面带入数据
|
// isCooking=false:从前一页面带入主辅材数据;isCooking=true:从数据库查询
|
||||||
goodsList = getSerializable(GOODS_LIST) as MutableList<CookFoodGoodsEntity>?
|
if (food?.isCooking == false) {
|
||||||
|
goodsList = getSerializable(GOODS_LIST) as MutableList<CookFoodGoodsEntity>?
|
||||||
|
Log.d(TAG, "onCreate: goodsList=${goodsList.toJsonString()}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setTitleBar(titleBarAction = {
|
setTitleBar(titleBarAction = {
|
||||||
it.visible()
|
it.visible()
|
||||||
@@ -102,11 +114,17 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
it.text = food?.foodName
|
it.text = food?.foodName
|
||||||
}, rightIconActon = {
|
}, rightIconActon = {
|
||||||
it.gone()
|
it.gone()
|
||||||
it.setImageResource(R.drawable.ic_setting)
|
}, backAction = {
|
||||||
|
it.setOnClickListener {
|
||||||
|
remindSaveDataDialog()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
addViewListener()
|
addViewListener()
|
||||||
loadSlotsThenObserveScales()
|
loadSlotsThenObserveScales()
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
|
remindSaveDataDialog()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 RecyclerView,2列 GridLayoutManager */
|
/** 初始化 RecyclerView,2列 GridLayoutManager */
|
||||||
@@ -118,7 +136,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 从 Room 加载槽位配置后,开始订阅子设备秤数据
|
* 从 Room 加载槽位配置后,开始订阅子设备秤数据
|
||||||
* 确保 slotMap 就绪后再处理秤数据,避免名称为空
|
* isCooking=true 时先从数据库查询 goodsList,筛选调料预填充 adapter,再开始观测
|
||||||
*/
|
*/
|
||||||
private fun loadSlotsThenObserveScales() {
|
private fun loadSlotsThenObserveScales() {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
@@ -127,7 +145,29 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
slots.forEach { slot ->
|
slots.forEach { slot ->
|
||||||
slotMap["${slot.deviceId}#${slot.address}"] = slot.goodsId to slot.goodsName
|
slotMap["${slot.deviceId}#${slot.address}"] = slot.goodsId to slot.goodsName
|
||||||
}
|
}
|
||||||
observeScaleData()
|
if (food?.isCooking == true) {
|
||||||
|
// 制作中:从数据库查询 goodsList,筛选调料数据预填充 adapter
|
||||||
|
val foodId = food?.foodId ?: return@withContext
|
||||||
|
val cookMode = food?.cookMode ?: return@withContext
|
||||||
|
appViewModel.getCookFoodGoodsList(foodId, cookMode) { list ->
|
||||||
|
goodsList = list
|
||||||
|
list.filter { it.materialType == 3 }.forEach { item ->
|
||||||
|
val name = item.goodsName ?: ""
|
||||||
|
val weight = item.useWeight ?: 0.0
|
||||||
|
baseSeasoningMap[name] = (item.goodsId) to weight
|
||||||
|
seasoningAdapter.updateItem(
|
||||||
|
SeasoningWeightAdapter.Item(
|
||||||
|
goodsId = item.goodsId,
|
||||||
|
goodsName = name,
|
||||||
|
useWeight = weight
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
observeScaleData()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
observeScaleData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,33 +214,34 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按 goodsName 聚合 rawWeightMap,将同名调料的用量累加后推给 adapter
|
* 按 goodsName 聚合 rawWeightMap,叠加历史用量后推给 adapter
|
||||||
* 聚合后总量 < 0.5g 则从 adapter 移除
|
* isCooking=true 时只新增,不移除(历史调料数据不可减少)
|
||||||
*/
|
*/
|
||||||
private fun refreshAdapterByName(goodsName: String) {
|
private fun refreshAdapterByName(goodsName: String) {
|
||||||
val grouped = rawWeightMap.values.filter { it.second == goodsName }
|
val grouped = rawWeightMap.values.filter { it.second == goodsName }
|
||||||
if (grouped.isEmpty()) {
|
val newWeight = grouped.sumOf { it.third }.roundedOneDecimalPlace()
|
||||||
seasoningAdapter.removeItem(goodsName)
|
val (baseGoodsId, baseWeight) = baseSeasoningMap[goodsName] ?: ("" to 0.0)
|
||||||
|
val totalWeight = (newWeight + baseWeight).roundedOneDecimalPlace()
|
||||||
|
if (totalWeight < 0.5) {
|
||||||
|
// 制作中模式:已有历史数据,不允许移除
|
||||||
|
if (food?.isCooking != true) {
|
||||||
|
seasoningAdapter.removeItem(goodsName)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val totalWeight = grouped.sumOf { it.third }.roundedOneDecimalPlace()
|
val goodsId = grouped.firstOrNull()?.first?.takeIf { it.isNotEmpty() } ?: baseGoodsId
|
||||||
if (totalWeight < 0.5) {
|
seasoningAdapter.updateItem(
|
||||||
seasoningAdapter.removeItem(goodsName)
|
SeasoningWeightAdapter.Item(
|
||||||
} else {
|
goodsId = goodsId,
|
||||||
seasoningAdapter.updateItem(
|
goodsName = goodsName,
|
||||||
SeasoningWeightAdapter.Item(
|
useWeight = totalWeight
|
||||||
goodsId = grouped.first().first,
|
|
||||||
goodsName = goodsName,
|
|
||||||
useWeight = totalWeight
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addViewListener() {
|
private fun addViewListener() {
|
||||||
|
|
||||||
binding.btnCook.clickWithDebounce { cook() }
|
binding.btnCook.clickWithDebounce { cook() }
|
||||||
|
binding.btnWeightClear.clickWithDebounce { WeightUtil.tareTwo(2) }
|
||||||
binding.btnSubmit.clickWithDebounce {
|
binding.btnSubmit.clickWithDebounce {
|
||||||
if (cookFoodEntity.foodWeight <= 0.toDouble()) {
|
if (cookFoodEntity.foodWeight <= 0.toDouble()) {
|
||||||
toast("未识别到菜品熟重")
|
toast("未识别到菜品熟重")
|
||||||
@@ -212,8 +253,14 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
// 监听主设备 2格秤的熟重
|
// 监听主设备 2格秤的熟重
|
||||||
WeightUtil.addWeightListener(TAG) { address, _, weight ->
|
WeightUtil.addWeightListener(TAG) { address, _, weight ->
|
||||||
if (address == AddressUtil.TWO) {
|
if (address == AddressUtil.TWO) {
|
||||||
cookFoodEntity.foodWeight = weight.toDouble()
|
cookFoodEntity.foodWeight = weight
|
||||||
binding.tvTotalWeight.text = "${weight / 1000f}"
|
if (weight > 1000) {
|
||||||
|
binding.tvTotalWeight.text = "${(weight / 1000f).roundedDecimalPlace(3)}"
|
||||||
|
binding.tvWeightUnit.text = "千克"
|
||||||
|
} else {
|
||||||
|
binding.tvTotalWeight.text = "$weight"
|
||||||
|
binding.tvWeightUnit.text = "克"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +278,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
showLoading()
|
showLoading()
|
||||||
|
|
||||||
// 将调料数据转为 CookFoodGoodsEntity 追加到 goodsList
|
// 将调料数据转为 CookFoodGoodsEntity 追加到 goodsList
|
||||||
val typeToken = object : TypeToken<List<CookFoodGoodsEntity>>() {}
|
// val typeToken = object : TypeToken<List<CookFoodGoodsEntity>>() {}
|
||||||
val tempSeasoningList = seasoningData.map { item ->
|
val tempSeasoningList = seasoningData.map { item ->
|
||||||
CookFoodGoodsEntity().also { entity ->
|
CookFoodGoodsEntity().also { entity ->
|
||||||
entity.goodsId = item.goodsId
|
entity.goodsId = item.goodsId
|
||||||
@@ -348,7 +395,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
val db = BaseApp.instance!!.database
|
val db = BaseApp.instance!!.database
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
val factory = AppFactory(AppRepository(db.appDao(), db.seasoningSlotDao()))
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,4 +403,18 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
WeightUtil.removeWeightListener(TAG)
|
WeightUtil.removeWeightListener(TAG)
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未保存数据提醒dialog
|
||||||
|
*/
|
||||||
|
private fun remindSaveDataDialog() {
|
||||||
|
CommonDialog(this)
|
||||||
|
.setTitle("温馨提示")
|
||||||
|
.setContent("请确认是否存在未保存的数据?")
|
||||||
|
.setNegativeButton("取消,留在页面")
|
||||||
|
.setNeutralButton("返回上页,不保存") { finish() }
|
||||||
|
.setPositiveButton("保存为烹饪中菜品") { cook() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,28 +10,34 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import androidx.camera.view.PreviewView
|
||||||
|
import androidx.core.view.doOnLayout
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.FoodCollectionAdapter
|
import com.shuwei.dish.match.adapter.FoodCollectionAdapter
|
||||||
import com.shuwei.dish.match.base.BaseFragment
|
import com.shuwei.dish.match.base.BaseFragment
|
||||||
import com.shuwei.dish.match.databinding.FragmentCollectBinding
|
import com.shuwei.dish.match.databinding.FragmentCollectBinding
|
||||||
|
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
||||||
import com.shuwei.dish.match.dialog.Loading
|
import com.shuwei.dish.match.dialog.Loading
|
||||||
import com.shuwei.dish.match.objbox.FoodCollectionBean
|
import com.shuwei.dish.match.objbox.FoodCollectionBean
|
||||||
import com.shuwei.dish.match.objbox.FoodModule
|
import com.shuwei.dish.match.objbox.FoodModule
|
||||||
import com.shuwei.dish.match.ui.SettingActivity
|
import com.shuwei.dish.match.ui.SingleFragmentActivity
|
||||||
import com.shuwei.dish.match.utils.BitmapSaver
|
import com.shuwei.dish.match.utils.BitmapSaver
|
||||||
|
import com.shuwei.dish.match.utils.CameraUtils
|
||||||
import com.shuwei.dish.match.utils.Debouncer
|
import com.shuwei.dish.match.utils.Debouncer
|
||||||
import com.shuwei.dish.match.utils.ImageUtil
|
import com.shuwei.dish.match.utils.ImageUtil
|
||||||
import com.shuwei.dish.match.utils.LogSaveUtil
|
import com.shuwei.dish.match.utils.LogSaveUtil
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
class CollectFragment : BaseFragment<FragmentCollectBinding>(){
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "CollectFragment"
|
private const val TAG = "CollectFragment"
|
||||||
const val MAX_COUNT = 9
|
const val MAX_COUNT = 18
|
||||||
}
|
}
|
||||||
|
|
||||||
private var selectedFoodId: String? = ""
|
private var selectedFoodId: String? = ""
|
||||||
@@ -58,7 +64,8 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
private val debouncer = Debouncer(2000)
|
private val debouncer = Debouncer(2000)
|
||||||
private lateinit var settingActivity: SettingActivity
|
// private lateinit var settingActivity: SettingActivity
|
||||||
|
private lateinit var currentActivity: SingleFragmentActivity
|
||||||
|
|
||||||
private val collectionAdapter: FoodCollectionAdapter by lazy {
|
private val collectionAdapter: FoodCollectionAdapter by lazy {
|
||||||
FoodCollectionAdapter(foodCollectionList).apply {
|
FoodCollectionAdapter(foodCollectionList).apply {
|
||||||
@@ -168,7 +175,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
showWaitingDialog("采集中……")
|
showWaitingDialog("采集中……")
|
||||||
settingActivity.takePhoto(succCallback = cameraCallback, failCallback = { errMsg ->
|
cameraUtils.takePhoto(succCallback = cameraCallback, failCallback = { errMsg ->
|
||||||
hideWaitingDialog()
|
hideWaitingDialog()
|
||||||
// toast("拍照异常,请重新操作")
|
// toast("拍照异常,请重新操作")
|
||||||
// if (cameraErrorCount >= 10) {
|
// if (cameraErrorCount >= 10) {
|
||||||
@@ -183,9 +190,22 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
settingActivity = activity as SettingActivity
|
currentActivity = activity as SingleFragmentActivity
|
||||||
// 首次显示 CollectFragment 时初始化相机
|
// 首次显示 CollectFragment 时初始化相机
|
||||||
settingActivity.initCamera(binding.flCameraPreview)
|
initCamera(binding.flCameraPreview)
|
||||||
|
currentActivity.setLifecycleCallback(object : SingleFragmentActivity.LifecycleCallback {
|
||||||
|
override fun onActivityResume() {
|
||||||
|
// 首次进入时 previewView 尚未 attach,由 doOnLayout 负责首次 bind
|
||||||
|
// 从后台切回时 previewView 已 attach,直接 bind 恢复预览
|
||||||
|
if (::previewView.isInitialized && previewView.isAttachedToWindow) {
|
||||||
|
cameraUtils.bind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityPause() {
|
||||||
|
cameraUtils.unbind()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.rvFoodList.let {
|
binding.rvFoodList.let {
|
||||||
it.layoutManager =
|
it.layoutManager =
|
||||||
@@ -340,7 +360,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (isVisible.not()) return
|
// 不使用 isVisible 判断,首次打开时 View 尚未 attach 到 Window,isVisible 会返回 false 导致遮罩永不隐藏
|
||||||
binding.llCameraFlag.run {
|
binding.llCameraFlag.run {
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
postDelayed({
|
postDelayed({
|
||||||
@@ -361,7 +381,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
|
|
||||||
private fun searchByFoodName(name: String, block: (String) -> Unit) {}
|
private fun searchByFoodName(name: String, block: (String) -> Unit) {}
|
||||||
private fun hideWaitingDialog() {
|
private fun hideWaitingDialog() {
|
||||||
settingActivity.dismissLoading()
|
currentActivity.dismissLoading()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showWaitingDialog(msg: String) {
|
private fun showWaitingDialog(msg: String) {
|
||||||
@@ -369,6 +389,34 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>() {
|
|||||||
Loading.updateContent(msg)
|
Loading.updateContent(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
settingActivity.showLoading(msg)
|
currentActivity.showLoading(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var previewView: PreviewView
|
||||||
|
|
||||||
|
private val cameraUtils: CameraUtils by lazy {
|
||||||
|
CameraUtils(requireActivity())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化相机
|
||||||
|
* @param container 相机预览容器
|
||||||
|
*/
|
||||||
|
fun initCamera(container: ViewGroup) {
|
||||||
|
cameraUtils.initCamera()
|
||||||
|
val previewBinding =
|
||||||
|
LayoutCameraPreviewBinding.inflate(layoutInflater, container)
|
||||||
|
previewView = previewBinding.previewView.also {
|
||||||
|
it.updateLayoutParams {
|
||||||
|
width = 456.dp
|
||||||
|
height = 342.dp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cameraUtils.setPreviewController(previewView)
|
||||||
|
// doOnLayout 确保 previewView 测量完成(有有效尺寸和 Surface)后再 bind,解决首次打开无预览问题
|
||||||
|
previewView.doOnLayout {
|
||||||
|
cameraUtils.bind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,46 +1,22 @@
|
|||||||
package com.shuwei.dish.match.ui.fragment
|
package com.shuwei.dish.match.ui.fragment
|
||||||
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Bundle
|
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.AbsoluteSizeSpan
|
import android.text.style.AbsoluteSizeSpan
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.text.style.LineHeightSpan
|
import android.text.style.LineHeightSpan
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.util.Log
|
|
||||||
import android.util.SparseArray
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.forEach
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
|
||||||
import com.shuwei.dish.match.base.BaseFragment
|
import com.shuwei.dish.match.base.BaseFragment
|
||||||
import com.shuwei.dish.match.databinding.FragmentDeviceConfigBinding
|
import com.shuwei.dish.match.databinding.FragmentDeviceConfigBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.dialog.SeasoningSearchDialog
|
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
|
||||||
import com.shuwei.dish.match.entity.ResetReasoningRecord
|
|
||||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
|
||||||
import com.shuwei.dish.match.utils.AddressUtil
|
|
||||||
import com.shuwei.dish.match.utils.JsonAssetsLoader
|
|
||||||
import com.shuwei.dish.match.utils.MultiClickDetector
|
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
|
||||||
import com.shuwei.dish.match.utils.ext.appendText
|
|
||||||
import com.shuwei.dish.match.utils.ext.buildSpannableString
|
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
import com.shuwei.dish.match.ui.SamplingListActivity
|
import com.shuwei.dish.match.ui.SamplingListActivity
|
||||||
import com.shuwei.dish.match.ui.SelectDishActivity
|
import com.shuwei.dish.match.ui.SelectDishActivity
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
|
import com.shuwei.dish.match.utils.ext.appendText
|
||||||
|
import com.shuwei.dish.match.utils.ext.buildSpannableString
|
||||||
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,10 +41,10 @@ class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
|||||||
|
|
||||||
// private lateinit var appViewModel: AppViewModel
|
// private lateinit var appViewModel: AppViewModel
|
||||||
|
|
||||||
private val weightArray = SparseArray<Double>()
|
// private val weightArray = SparseArray<Double>()
|
||||||
private val addressArray = AddressUtil.getWeighAddressArray()
|
// private val addressArray = AddressUtil.getWeighAddressArray()
|
||||||
private var seasoningItems = mutableListOf<SeasoningEntity>()
|
// private var seasoningItems = mutableListOf<SeasoningEntity>()
|
||||||
private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800)
|
// private val detector = MultiClickDetector(targetCount = 10, intervalMs = 800)
|
||||||
|
|
||||||
override fun inflateBinding(
|
override fun inflateBinding(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
@@ -77,7 +53,7 @@ class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
|||||||
return FragmentDeviceConfigBinding.inflate(inflater, container, false)
|
return FragmentDeviceConfigBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize(){
|
override fun initialize() {
|
||||||
initViewModel()
|
initViewModel()
|
||||||
initUI()
|
initUI()
|
||||||
// addWeighListener()
|
// addWeighListener()
|
||||||
@@ -140,7 +116,8 @@ class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
|||||||
loadCookSpan()
|
loadCookSpan()
|
||||||
loadSamplingSpan(isClicked = true)
|
loadSamplingSpan(isClicked = true)
|
||||||
activity?.startActivity<SamplingListActivity> {
|
activity?.startActivity<SamplingListActivity> {
|
||||||
putExtra(SamplingListActivity.IS_CONFIG_PAGE, true) }
|
putExtra(SamplingListActivity.IS_CONFIG_PAGE, true)
|
||||||
|
}
|
||||||
activity?.finish()
|
activity?.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ import com.shuwei.dish.match.base.DeviceRole
|
|||||||
import com.shuwei.dish.match.base.GlobalData
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
import com.shuwei.dish.match.databinding.FragmentSeasoningConfigBinding
|
import com.shuwei.dish.match.databinding.FragmentSeasoningConfigBinding
|
||||||
import com.shuwei.dish.match.dialog.SeasoningSelectDialog
|
import com.shuwei.dish.match.dialog.SeasoningSelectDialog
|
||||||
|
import com.shuwei.dish.match.entity.SeasoningEntity
|
||||||
import com.shuwei.dish.match.entity.SeasoningSlotEntity
|
import com.shuwei.dish.match.entity.SeasoningSlotEntity
|
||||||
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
import com.shuwei.dish.match.scale.ScaleDeviceConfig
|
||||||
import com.shuwei.dish.match.scale.ScaleEvent
|
import com.shuwei.dish.match.scale.ScaleEvent
|
||||||
import com.shuwei.dish.match.scale.ScaleServiceManager
|
import com.shuwei.dish.match.scale.ScaleServiceManager
|
||||||
import com.shuwei.dish.match.scale.ScaleEvent.SlotConfig
|
import com.shuwei.dish.match.scale.ScaleEvent.SlotConfig
|
||||||
import com.shuwei.dish.match.ui.SettingActivity
|
import com.shuwei.dish.match.ui.SingleFragmentActivity
|
||||||
|
import com.shuwei.dish.match.utils.SizeTool
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -35,8 +37,10 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SeasoningConfigFragment"
|
private const val TAG = "SeasoningConfigFragment"
|
||||||
|
|
||||||
/** 重量增加阈值(克),超过此值才触发高亮 */
|
/** 重量增加阈值(克),超过此值才触发高亮 */
|
||||||
private const val WEIGHT_DELTA_THRESHOLD = 10.0
|
private const val WEIGHT_DELTA_THRESHOLD = 10.0
|
||||||
|
|
||||||
/** 高亮自动恢复时间(毫秒) */
|
/** 高亮自动恢复时间(毫秒) */
|
||||||
private const val HIGHLIGHT_DURATION_MS = 15_000L
|
private const val HIGHLIGHT_DURATION_MS = 15_000L
|
||||||
}
|
}
|
||||||
@@ -46,21 +50,28 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
container: ViewGroup?
|
container: ViewGroup?
|
||||||
) = FragmentSeasoningConfigBinding.inflate(inflater, container, false)
|
) = FragmentSeasoningConfigBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
private lateinit var settingActivity: SettingActivity
|
private lateinit var currentActivity: SingleFragmentActivity
|
||||||
// private lateinit var appViewModel: AppViewModel
|
// private lateinit var appViewModel: AppViewModel
|
||||||
|
|
||||||
private val adapter22 by lazy { buildAdapter22() }
|
private val adapter22 by lazy { buildAdapter22() }
|
||||||
private val adapter18 by lazy { Seasoning18GridAdapter(showNameOnly = true) }
|
private val adapter18 by lazy {
|
||||||
|
Seasoning18GridAdapter(
|
||||||
|
showNameOnly = true,
|
||||||
|
leftRightSpace = 20.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */
|
/** 各秤的上一次重量快照,key 格式 "{deviceId}#{address}",用于计算 delta */
|
||||||
private val weightSnapshot = mutableMapOf<String, Double>()
|
private val weightSnapshot = mutableMapOf<String, Double>()
|
||||||
|
|
||||||
/** 主线程 Handler,用于延迟清除高亮 */
|
/** 主线程 Handler,用于延迟清除高亮 */
|
||||||
private val mainHandler = Handler(Looper.getMainLooper())
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
/** 当前高亮清除任务,新高亮触发时取消旧任务 */
|
/** 当前高亮清除任务,新高亮触发时取消旧任务 */
|
||||||
private var clearHighlightRunnable: Runnable? = null
|
private var clearHighlightRunnable: Runnable? = null
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
settingActivity = activity as SettingActivity
|
currentActivity = activity as SingleFragmentActivity
|
||||||
// initViewModel()
|
// initViewModel()
|
||||||
setupRecyclerViews()
|
setupRecyclerViews()
|
||||||
bindAdapterClicks()
|
bindAdapterClicks()
|
||||||
@@ -72,62 +83,67 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
/** 绑定油盆格子点击,弹出调料选择弹窗并保存到 DEVICE_ID_1 */
|
/** 绑定油盆格子点击,弹出调料选择弹窗并保存到 DEVICE_ID_1 */
|
||||||
private fun bindOilSlotClick() {
|
private fun bindOilSlotClick() {
|
||||||
binding.tvOilSlot.setOnClickListener {
|
binding.tvOilSlot.setOnClickListener {
|
||||||
SeasoningSelectDialog(
|
openSeasoningSelectDialog(0) { item ->
|
||||||
activity = settingActivity,
|
binding.tvOilSlot.text = item.goodsName ?: "-"
|
||||||
clickIndex = 0,
|
saveSlotAndBroadcast(
|
||||||
onItemSelected = { item ->
|
SeasoningSlotEntity(
|
||||||
binding.tvOilSlot.text = item.goodsName ?: "-"
|
deviceId = ScaleDeviceConfig.DEVICE_ID_1,
|
||||||
saveSlotAndBroadcast(
|
address = 1,
|
||||||
SeasoningSlotEntity(
|
goodsId = item.goodsId,
|
||||||
deviceId = ScaleDeviceConfig.DEVICE_ID_1,
|
goodsName = item.goodsName ?: ""
|
||||||
address = 1,
|
|
||||||
goodsId = item.goodsId,
|
|
||||||
goodsName = item.goodsName ?: ""
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
).show()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 绑定两个 Adapter 的格子点击,弹出调料选择弹窗 */
|
/** 绑定两个 Adapter 的格子点击,弹出调料选择弹窗 */
|
||||||
private fun bindAdapterClicks() {
|
private fun bindAdapterClicks() {
|
||||||
adapter22.onItemClick = { scaleData, position ->
|
adapter22.onItemClick = { scaleData, position ->
|
||||||
SeasoningSelectDialog(
|
openSeasoningSelectDialog(position) { item ->
|
||||||
activity = settingActivity,
|
adapter22.updateItemName(position, item.goodsName ?: "")
|
||||||
clickIndex = position,
|
saveSlotAndBroadcast(
|
||||||
onItemSelected = { item ->
|
SeasoningSlotEntity(
|
||||||
adapter22.updateItemName(position, item.goodsName ?: "")
|
deviceId = ScaleDeviceConfig.DEVICE_ID_22,
|
||||||
saveSlotAndBroadcast(
|
address = scaleData.address,
|
||||||
SeasoningSlotEntity(
|
goodsId = item.goodsId,
|
||||||
deviceId = ScaleDeviceConfig.DEVICE_ID_22,
|
goodsName = item.goodsName ?: ""
|
||||||
address = scaleData.address,
|
|
||||||
goodsId = item.goodsId,
|
|
||||||
goodsName = item.goodsName ?: ""
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
).show()
|
}
|
||||||
}
|
}
|
||||||
adapter18.onItemClick = { scaleData, position ->
|
adapter18.onItemClick = { scaleData, position ->
|
||||||
SeasoningSelectDialog(
|
openSeasoningSelectDialog(position) { item ->
|
||||||
activity = settingActivity,
|
adapter18.updateItemName(position, item.goodsName ?: "")
|
||||||
clickIndex = position,
|
saveSlotAndBroadcast(
|
||||||
onItemSelected = { item ->
|
SeasoningSlotEntity(
|
||||||
adapter18.updateItemName(position, item.goodsName ?: "")
|
deviceId = ScaleDeviceConfig.DEVICE_ID_18,
|
||||||
saveSlotAndBroadcast(
|
address = scaleData.address,
|
||||||
SeasoningSlotEntity(
|
goodsId = item.goodsId,
|
||||||
deviceId = ScaleDeviceConfig.DEVICE_ID_18,
|
goodsName = item.goodsName ?: ""
|
||||||
address = scaleData.address,
|
|
||||||
goodsId = item.goodsId,
|
|
||||||
goodsName = item.goodsName ?: ""
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
).show()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开调料选择弹窗
|
||||||
|
*
|
||||||
|
* @param position 格子位置
|
||||||
|
* @param callback 调料选择回调
|
||||||
|
*/
|
||||||
|
private fun openSeasoningSelectDialog(
|
||||||
|
position: Int,
|
||||||
|
callback: (item: SeasoningEntity) -> Unit
|
||||||
|
) {
|
||||||
|
SeasoningSelectDialog(
|
||||||
|
activity = currentActivity,
|
||||||
|
clickIndex = position,
|
||||||
|
onItemSelected = callback
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将单个槽位写入 Room,再读取全量配置广播给子设备
|
* 将单个槽位写入 Room,再读取全量配置广播给子设备
|
||||||
* 仅主设备执行广播,子设备不调用此方法
|
* 仅主设备执行广播,子设备不调用此方法
|
||||||
@@ -150,24 +166,24 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
// appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
// appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
private val size by lazy { SizeTool.getFlexLayoutSize(20.dp) }
|
||||||
|
|
||||||
/** 构建上层(22格)Adapter,需要先计算格子尺寸 */
|
/** 构建上层(22格)Adapter,需要先计算格子尺寸 */
|
||||||
private fun buildAdapter22(): Seasoning22GridAdapter {
|
private fun buildAdapter22(): Seasoning22GridAdapter {
|
||||||
val usable = resources.displayMetrics.widthPixels - 8 * 4.dp - 10.dp
|
return Seasoning22GridAdapter(
|
||||||
val smallSize = usable / 9
|
largeSize = size.largeSize,
|
||||||
val largeSize = (usable - smallSize * 6) / 2
|
smallSize = size.smallSize,
|
||||||
return Seasoning22GridAdapter(largeSize, smallSize, showNameOnly = true)
|
showNameOnly = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 配置两个 RecyclerView */
|
/** 配置两个 RecyclerView */
|
||||||
private fun setupRecyclerViews() {
|
private fun setupRecyclerViews() {
|
||||||
// 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式
|
// 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式
|
||||||
// rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致
|
// rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致
|
||||||
val screenWidth = resources.displayMetrics.widthPixels
|
|
||||||
val usable = screenWidth - 8 * 4.dp - 10.dp
|
|
||||||
val smallSize = usable / 9
|
|
||||||
val rvTopHeight = smallSize * 3 + 3 * 4.dp
|
|
||||||
binding.rvTop.apply {
|
binding.rvTop.apply {
|
||||||
layoutParams = layoutParams.also { it.height = rvTopHeight }
|
layoutParams = layoutParams.also { it.height = size.rvHeight }
|
||||||
layoutManager = FlexboxLayoutManager(requireContext()).apply {
|
layoutManager = FlexboxLayoutManager(requireContext()).apply {
|
||||||
flexDirection = FlexDirection.COLUMN
|
flexDirection = FlexDirection.COLUMN
|
||||||
flexWrap = FlexWrap.WRAP
|
flexWrap = FlexWrap.WRAP
|
||||||
@@ -205,7 +221,8 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
}
|
}
|
||||||
// 加载油盆格子名称(address=1)
|
// 加载油盆格子名称(address=1)
|
||||||
val oilSlot = slotsOil.firstOrNull { it.address == 1 }
|
val oilSlot = slotsOil.firstOrNull { it.address == 1 }
|
||||||
binding.tvOilSlot.text = if (oilSlot != null && oilSlot.goodsName.isNotEmpty()) oilSlot.goodsName else "-"
|
binding.tvOilSlot.text =
|
||||||
|
if (oilSlot != null && oilSlot.goodsName.isNotEmpty()) oilSlot.goodsName else "-"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +240,10 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
* - STATE_STABLE:无条件更新基准(覆盖取走调料/归零等场景)
|
* - STATE_STABLE:无条件更新基准(覆盖取走调料/归零等场景)
|
||||||
*/
|
*/
|
||||||
private fun addWeightListener() {
|
private fun addWeightListener() {
|
||||||
Log.d(TAG, "addWeightListener: 注册监听, deviceId=${GlobalData.deviceId}, role=${GlobalData.deviceRole}")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"addWeightListener: 注册监听, deviceId=${GlobalData.deviceId}, role=${GlobalData.deviceRole}"
|
||||||
|
)
|
||||||
|
|
||||||
if (GlobalData.deviceRole == DeviceRole.MASTER) {
|
if (GlobalData.deviceRole == DeviceRole.MASTER) {
|
||||||
// 主设备:通过 allScales StateFlow 观测所有秤(含远端子设备秤)
|
// 主设备:通过 allScales StateFlow 观测所有秤(含远端子设备秤)
|
||||||
@@ -243,14 +263,21 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
val delta = data.weight - baseline
|
val delta = data.weight - baseline
|
||||||
Log.d(TAG, "allScales: key=$key address=${data.address} state=${data.state} weight=${data.weight} baseline=$baseline delta=$delta")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"allScales: key=$key address=${data.address} state=${data.state} weight=${data.weight} baseline=$baseline delta=$delta"
|
||||||
|
)
|
||||||
when {
|
when {
|
||||||
// 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发
|
// 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发
|
||||||
data.state == WeightUtil.STATE_STABLE && delta > WEIGHT_DELTA_THRESHOLD -> {
|
data.state == WeightUtil.STATE_STABLE && delta > WEIGHT_DELTA_THRESHOLD -> {
|
||||||
weightSnapshot[snapshotKey] = data.weight
|
weightSnapshot[snapshotKey] = data.weight
|
||||||
Log.d(TAG, "allScales: 触发高亮 key=$key address=${data.address} delta=$delta")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"allScales: 触发高亮 key=$key address=${data.address} delta=$delta"
|
||||||
|
)
|
||||||
triggerHighlight(data.deviceId, data.address, delta)
|
triggerHighlight(data.deviceId, data.address, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
data.state == WeightUtil.STATE_STABLE -> {
|
data.state == WeightUtil.STATE_STABLE -> {
|
||||||
weightSnapshot[snapshotKey] = data.weight
|
weightSnapshot[snapshotKey] = data.weight
|
||||||
}
|
}
|
||||||
@@ -263,7 +290,10 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
WeightUtil.addWeightListener(TAG) { address, state, weight ->
|
WeightUtil.addWeightListener(TAG) { address, state, weight ->
|
||||||
val snapshotKey = "${GlobalData.deviceId}#$address"
|
val snapshotKey = "${GlobalData.deviceId}#$address"
|
||||||
val baseline = weightSnapshot[snapshotKey]
|
val baseline = weightSnapshot[snapshotKey]
|
||||||
Log.d(TAG, "onWeight: address=$address state=$state weight=$weight baseline=$baseline")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"onWeight: address=$address state=$state weight=$weight baseline=$baseline"
|
||||||
|
)
|
||||||
|
|
||||||
if (baseline == null) {
|
if (baseline == null) {
|
||||||
weightSnapshot[snapshotKey] = weight
|
weightSnapshot[snapshotKey] = weight
|
||||||
@@ -271,7 +301,10 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val delta = weight - baseline
|
val delta = weight - baseline
|
||||||
Log.d(TAG, "onWeight: address=$address state=$state weight=$weight baseline=$baseline delta=$delta")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"onWeight: address=$address state=$state weight=$weight baseline=$baseline delta=$delta"
|
||||||
|
)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
// 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发
|
// 仅在秤稳定后判断增量,避免取走物品时手部冲力造成误触发
|
||||||
@@ -280,6 +313,7 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
Log.d(TAG, "onWeight: 触发高亮 address=$address delta=$delta")
|
Log.d(TAG, "onWeight: 触发高亮 address=$address delta=$delta")
|
||||||
triggerHighlight(GlobalData.deviceId, address, delta)
|
triggerHighlight(GlobalData.deviceId, address, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
state == WeightUtil.STATE_STABLE -> {
|
state == WeightUtil.STATE_STABLE -> {
|
||||||
weightSnapshot[snapshotKey] = weight
|
weightSnapshot[snapshotKey] = weight
|
||||||
}
|
}
|
||||||
@@ -302,7 +336,10 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
val pos18 = if (sourceDeviceId == ScaleDeviceConfig.DEVICE_ID_18)
|
val pos18 = if (sourceDeviceId == ScaleDeviceConfig.DEVICE_ID_18)
|
||||||
ScaleDeviceConfig.SCALE_ORDER_18.indexOf(address) else -1
|
ScaleDeviceConfig.SCALE_ORDER_18.indexOf(address) else -1
|
||||||
|
|
||||||
Log.d(TAG, "triggerHighlight: sourceDeviceId=$sourceDeviceId address=$address pos22=$pos22 pos18=$pos18")
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"triggerHighlight: sourceDeviceId=$sourceDeviceId address=$address pos22=$pos22 pos18=$pos18"
|
||||||
|
)
|
||||||
|
|
||||||
// 两个列表都不包含该地址,忽略
|
// 两个列表都不包含该地址,忽略
|
||||||
if (pos22 < 0 && pos18 < 0) {
|
if (pos22 < 0 && pos18 < 0) {
|
||||||
@@ -318,6 +355,7 @@ class SeasoningConfigFragment : BaseFragment<FragmentSeasoningConfigBinding>() {
|
|||||||
adapter22.highlightPosition(pos22)
|
adapter22.highlightPosition(pos22)
|
||||||
adapter18.clearHighlight()
|
adapter18.clearHighlight()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
adapter18.highlightPosition(pos18)
|
adapter18.highlightPosition(pos18)
|
||||||
adapter22.clearHighlight()
|
adapter22.clearHighlight()
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class CameraUtils(private var activity: ComponentActivity) {
|
|||||||
)
|
)
|
||||||
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||||
}
|
}
|
||||||
bind()
|
// bind() 由外部在 previewView attach 到窗口后调用,避免首次无预览
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (isCameraReady.not()) {
|
// if (isCameraReady.not()) {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.shuwei.dish.match.utils
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
|
|
||||||
|
data class FlexLayoutSize(
|
||||||
|
val smallSize: Int,
|
||||||
|
val largeSize: Int,
|
||||||
|
val rvHeight: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
object SizeTool {
|
||||||
|
|
||||||
|
fun getFlexLayoutSize(leftRightSpace: Int = 10.dp): FlexLayoutSize {
|
||||||
|
// 上层:FlexboxLayoutManager,仿 MasterScaleActivity 中 Scale22VH 的布局方式
|
||||||
|
// rvTop 高度 = 小格子尺寸 * 3行 + 3 * 间距,与 Scale22VH 保持一致
|
||||||
|
val screenWidth = BaseApp.instance!!.resources.displayMetrics.widthPixels
|
||||||
|
val usable = screenWidth - 8 * 4.dp - leftRightSpace
|
||||||
|
val smallSize = usable / 9
|
||||||
|
val largeSize = (usable - smallSize * 6) / 2
|
||||||
|
val rvHeight = smallSize * 3 + 3 * 4.dp
|
||||||
|
return FlexLayoutSize(smallSize, largeSize, rvHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -173,6 +173,17 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备是否已配置调料槽位
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @param action 回调,true 表示已配置,false 表示未配置
|
||||||
|
*/
|
||||||
|
fun hasSeasoningSlotConfig(deviceId: String, action: (Boolean) -> Unit) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
action(rep.hasSeasoningSlotConfig(deviceId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fun updateAll(list: MutableList<SeasoningEntity>) {
|
// fun updateAll(list: MutableList<SeasoningEntity>) {
|
||||||
// viewModelScope.launch {
|
// viewModelScope.launch {
|
||||||
// list.forEach {
|
// list.forEach {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.shuwei.dish.match.viewmodel.factory
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
import com.shuwei.dish.match.db.AppRepository
|
||||||
|
import com.shuwei.dish.match.db.dao.SeasoningSlotDao
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
@@ -59,6 +59,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/tvConnectionStatus"
|
app:layout_constraintTop_toBottomOf="@id/tvConnectionStatus"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
|
tools:itemCount="4"
|
||||||
tools:listitem="@layout/list_type_scale22"/>
|
tools:listitem="@layout/list_type_scale22"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -1,77 +1,172 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
tools:background="@color/bg_color"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!-- 底部导航菜单 -->
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/bottomMenu"
|
android:id="@+id/llCookMode"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="120dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:background="@android:color/transparent"
|
android:gravity="center_vertical"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginHorizontal="32dp"
|
||||||
android:layout_marginStart="15dp"
|
android:background="@drawable/shape_white_e6_12_corners"
|
||||||
android:layout_marginEnd="15dp"
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:elevation="8dp">
|
android:clipToOutline="true">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<TextView
|
||||||
android:id="@+id/btnDeviceConfig"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="70dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="设备切换"
|
android:text="餐品模式"
|
||||||
android:textSize="28sp"
|
android:textSize="32sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:background="@android:color/transparent" />
|
android:layout_marginStart="32dp"
|
||||||
|
android:textColor="@color/black333" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
<TextView
|
||||||
android:id="@+id/btnSeasoningConfig"
|
android:id="@+id/tvCurrentMode"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="70dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
tools:text="当前:制作模式"
|
||||||
android:text="调料配置"
|
|
||||||
android:textSize="26sp"
|
android:textSize="26sp"
|
||||||
android:background="@android:color/transparent" />
|
android:layout_marginStart="32dp"
|
||||||
|
android:textColor="@color/black999" />
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
|
||||||
android:id="@+id/btnFoodCollect"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="70dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="采集食材"
|
|
||||||
android:textSize="26sp"
|
|
||||||
android:background="@android:color/transparent" />
|
|
||||||
|
|
||||||
<!-- <androidx.appcompat.widget.AppCompatButton-->
|
|
||||||
<!-- android:id="@+id/btnDeviceRole"-->
|
|
||||||
<!-- android:layout_width="0dp"-->
|
|
||||||
<!-- android:layout_height="70dp"-->
|
|
||||||
<!-- android:layout_weight="1"-->
|
|
||||||
<!-- android:text="设备角色:子设备"-->
|
|
||||||
<!-- android:textSize="22sp"-->
|
|
||||||
<!-- android:background="@android:color/transparent" />-->
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatButton
|
|
||||||
android:id="@+id/btnScaleMonitor"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="70dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="秤数据监控"
|
|
||||||
android:textSize="26sp"
|
|
||||||
android:visibility="visible"
|
|
||||||
android:background="@android:color/transparent" />
|
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/ic_arrow_right2"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Fragment 容器 -->
|
<LinearLayout
|
||||||
<FrameLayout
|
android:id="@+id/llSeasoningConfig"
|
||||||
android:id="@+id/fragmentContainer"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="120dp"
|
||||||
android:layout_weight="1" />
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:background="@drawable/shape_white_e6_12_corners"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:clipToOutline="true">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="调料区设置"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:textColor="@color/black333" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/ic_arrow_right2"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llFoodCollect"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="120dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:background="@drawable/shape_white_e6_12_corners"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:clipToOutline="true">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="食材采样"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:textColor="@color/black333" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/ic_arrow_right2"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- <!– 底部导航菜单 –>-->
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:id="@+id/bottomMenu"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:orientation="horizontal"-->
|
||||||
|
<!-- android:background="@android:color/transparent"-->
|
||||||
|
<!-- android:layout_marginTop="10dp"-->
|
||||||
|
<!-- android:layout_marginBottom="10dp"-->
|
||||||
|
<!-- android:layout_marginStart="15dp"-->
|
||||||
|
<!-- android:layout_marginEnd="15dp"-->
|
||||||
|
<!-- android:elevation="8dp">-->
|
||||||
|
|
||||||
|
<!-- <androidx.appcompat.widget.AppCompatButton-->
|
||||||
|
<!-- android:id="@+id/btnDeviceConfig"-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="70dp"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:text="设备切换"-->
|
||||||
|
<!-- android:textSize="28sp"-->
|
||||||
|
<!-- android:textStyle="bold"-->
|
||||||
|
<!-- android:background="@android:color/transparent" />-->
|
||||||
|
|
||||||
|
<!-- <androidx.appcompat.widget.AppCompatButton-->
|
||||||
|
<!-- android:id="@+id/btnSeasoningConfig"-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="70dp"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:text="调料配置"-->
|
||||||
|
<!-- android:textSize="26sp"-->
|
||||||
|
<!-- android:background="@android:color/transparent" />-->
|
||||||
|
|
||||||
|
<!-- <androidx.appcompat.widget.AppCompatButton-->
|
||||||
|
<!-- android:id="@+id/btnFoodCollect"-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="70dp"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:text="采集食材"-->
|
||||||
|
<!-- android:textSize="26sp"-->
|
||||||
|
<!-- android:background="@android:color/transparent" />-->
|
||||||
|
|
||||||
|
<!-- <androidx.appcompat.widget.AppCompatButton-->
|
||||||
|
<!-- android:id="@+id/btnScaleMonitor"-->
|
||||||
|
<!-- android:layout_width="0dp"-->
|
||||||
|
<!-- android:layout_height="70dp"-->
|
||||||
|
<!-- android:layout_weight="1"-->
|
||||||
|
<!-- android:text="秤数据监控"-->
|
||||||
|
<!-- android:textSize="26sp"-->
|
||||||
|
<!-- android:visibility="visible"-->
|
||||||
|
<!-- android:background="@android:color/transparent" />-->
|
||||||
|
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
|
<!-- <!– Fragment 容器 –>-->
|
||||||
|
<!-- <FrameLayout-->
|
||||||
|
<!-- android:id="@+id/fragmentContainer"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="0dp"-->
|
||||||
|
<!-- android:layout_weight="1" />-->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="660dp"
|
android:layout_height="660dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
android:overScrollMode="never" />
|
android:overScrollMode="never" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -98,7 +100,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
android:includeFontPadding="false"
|
android:includeFontPadding="false"
|
||||||
android:text="千克"
|
tools:text="千克"
|
||||||
android:textColor="@color/black999"
|
android:textColor="@color/black999"
|
||||||
android:textSize="32sp" />
|
android:textSize="32sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -36,7 +36,9 @@
|
|||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
android:background="@color/gray_eb" />
|
android:background="@color/gray_eb" />
|
||||||
|
|
||||||
|
<!-- 2个按钮时显示(水平排列) -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutButtonsHorizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
@@ -69,4 +71,51 @@
|
|||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 3个按钮时显示(垂直排列,iOS风格) -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutButtonsVertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnTop"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/ripple_effect_light2"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="30sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/gray_eb" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnMiddle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/ripple_effect_light2"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="30sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/gray_eb" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btnBottom"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/ripple_effect_light2"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="0dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="0dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:paddingBottom="20dp"
|
android:paddingBottom="10dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:background="@drawable/shape_white_30_corners"
|
android:background="@drawable/shape_white_30_corners"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -94,6 +94,8 @@
|
|||||||
android:background="@drawable/shape_scale_cell"
|
android:background="@drawable/shape_scale_cell"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="-"
|
android:text="-"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:clipToOutline="true"
|
||||||
android:textColor="@color/home_title"
|
android:textColor="@color/home_title"
|
||||||
android:textSize="28sp" />
|
android:textSize="28sp" />
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="16dp"
|
android:background="@drawable/shape_scale_cell"
|
||||||
android:paddingEnd="16dp">
|
android:paddingHorizontal="16dp"
|
||||||
|
android:layout_marginHorizontal="4dp"
|
||||||
|
android:layout_marginVertical="4dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvSeasoningName"
|
android:id="@+id/tvSeasoningName"
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
android:background="@drawable/shape_scale_cell">
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:background="@drawable/shape_scale_cell"
|
||||||
|
android:clipToOutline="true">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvAddress"
|
android:id="@+id/tvAddress"
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="340dp"
|
android:layout_height="340dp"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:background="@drawable/shape_scale_cell"
|
android:background="@drawable/shape_scale_cell"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="8dp"
|
||||||
|
android:clipToOutline="true">
|
||||||
|
|
||||||
<!-- 秤编号 -->
|
<!-- 秤编号 -->
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:layout_marginBottom="2dp"
|
android:layout_marginBottom="2dp"
|
||||||
|
android:clipToOutline="true"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
android:background="@drawable/shape_scale_cell">
|
android:background="@drawable/shape_scale_cell">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_marginTop="5dp">
|
android:layout_marginTop="5dp">
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user