Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94e49eb344 | ||
|
|
69dc77f06e | ||
|
|
b69b8c10e8 | ||
|
|
0477fad57b | ||
|
|
da7b5b09a0 | ||
|
|
f1ffc67b9b | ||
|
|
910759c99e |
@@ -15,10 +15,12 @@ import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
|||||||
/**
|
/**
|
||||||
* 菜品识别结果弹窗,继承 BottomSheetDialog 确保只初始化一次
|
* 菜品识别结果弹窗,继承 BottomSheetDialog 确保只初始化一次
|
||||||
* @param activity 宿主 Activity
|
* @param activity 宿主 Activity
|
||||||
|
* @param onDismiss 弹窗关闭时的额外回调(可选)
|
||||||
* @param onItemSelected 用户点击某一菜品时的回调
|
* @param onItemSelected 用户点击某一菜品时的回调
|
||||||
*/
|
*/
|
||||||
class FoodRecognizeDialog(
|
class FoodRecognizeDialog(
|
||||||
private val activity: BaseActivity,
|
private val activity: BaseActivity,
|
||||||
|
private val onDismiss: (() -> Unit)? = null,
|
||||||
private val onItemSelected: (item: CookFoodGoodsEntity) -> Unit
|
private val onItemSelected: (item: CookFoodGoodsEntity) -> Unit
|
||||||
) : BottomSheetDialog(activity, R.style.BottomSheet) {
|
) : BottomSheetDialog(activity, R.style.BottomSheet) {
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ class FoodRecognizeDialog(
|
|||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setCancelable(true)
|
setCancelable(true)
|
||||||
behavior.skipCollapsed = false
|
behavior.skipCollapsed = false
|
||||||
setOnDismissListener { activity.hideStatusBar() }
|
setOnDismissListener { activity.hideStatusBar(); onDismiss?.invoke() }
|
||||||
binding.recyclerView.run {
|
binding.recyclerView.run {
|
||||||
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
||||||
adapter = this@FoodRecognizeDialog.adapter
|
adapter = this@FoodRecognizeDialog.adapter
|
||||||
|
|||||||
@@ -22,114 +22,94 @@ import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
|||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 食材搜索弹窗
|
* 食材搜索弹窗,继承 BottomSheetDialog 确保只初始化一次
|
||||||
|
* @param activity 宿主 Activity
|
||||||
|
* @param defGoodsName 默认填充的食材名称(可选)
|
||||||
|
* @param onItemSelected 用户点击某一食材时的回调
|
||||||
*/
|
*/
|
||||||
class FoodSearchDialog(
|
class FoodSearchDialog(
|
||||||
private var defGoodsName: String? = null
|
private val activity: BaseActivity,
|
||||||
) {
|
private val defGoodsName: String? = null,
|
||||||
companion object {
|
private val onItemSelected: (item: CookFoodGoodsEntity) -> Unit
|
||||||
const val TAG = "BottomDialog"
|
) : BottomSheetDialog(activity, R.style.BottomSheet) {
|
||||||
}
|
|
||||||
|
|
||||||
private var list = mutableListOf<CookFoodGoodsEntity>()
|
private val binding = DialogFoodSearchBinding.inflate(LayoutInflater.from(activity))
|
||||||
|
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||||
private lateinit var binding: DialogFoodSearchBinding
|
private val adapter = GoodsInfoSearchAdapter(list).apply {
|
||||||
private lateinit var searchAdapter: GoodsInfoSearchAdapter
|
|
||||||
private var goodsName: String? = null
|
|
||||||
|
|
||||||
private var activity: BaseActivity? = null
|
|
||||||
|
|
||||||
fun show(activity: BaseActivity, callback: (item: CookFoodGoodsEntity) -> Unit) {
|
|
||||||
this.activity = activity
|
|
||||||
//直接使用BottomSheetDialog
|
|
||||||
var dialog: BottomSheetDialog? = null
|
|
||||||
val inflater = LayoutInflater.from(activity)
|
|
||||||
binding = DialogFoodSearchBinding.inflate(inflater)
|
|
||||||
dialog = BottomSheetDialog(activity, R.style.BottomSheet).apply {
|
|
||||||
setContentView(binding.root)
|
|
||||||
setCancelable(true)
|
|
||||||
behavior.skipCollapsed = false // 跳过折叠状态
|
|
||||||
// behavior.peekHeight = 880.dp
|
|
||||||
// window?.setLayout(-1, 880.dp)
|
|
||||||
show()
|
|
||||||
setOnDismissListener {
|
|
||||||
activity.hideStatusBar()
|
|
||||||
}
|
|
||||||
binding.etSheetInput.requestFocus()
|
|
||||||
}
|
|
||||||
binding.tvSheetName.text = "食材检索"
|
|
||||||
binding.etSheetInput.run {
|
|
||||||
hint = "输入食材名称或速记码"
|
|
||||||
addTextChangedListener(afterTextChanged = { it: Editable? ->
|
|
||||||
if (it.isNullOrBlank()) {
|
|
||||||
list.clear()
|
|
||||||
searchAdapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
searchAdapter = GoodsInfoSearchAdapter(list).apply {
|
|
||||||
setOnItemClickListener { _, _, position ->
|
setOnItemClickListener { _, _, position ->
|
||||||
list[position].isClicked = true
|
list[position].isClicked = true
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
callback(list[position])
|
onItemSelected(list[position])
|
||||||
dialog?.dismiss()
|
dismiss()
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.recyclerView.run {
|
|
||||||
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
private var goodsName: String? = null
|
||||||
adapter = searchAdapter
|
private var pageNo = 1
|
||||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
private val pageSize = 50
|
||||||
override fun onScrollStateChanged(rv: RecyclerView, newState: Int) {
|
|
||||||
super.onScrollStateChanged(rv, newState);
|
init {
|
||||||
|
setContentView(binding.root)
|
||||||
|
setCancelable(true)
|
||||||
|
behavior.skipCollapsed = false
|
||||||
|
setOnDismissListener { activity.hideStatusBar() }
|
||||||
|
|
||||||
|
binding.tvSheetName.text = "食材检索"
|
||||||
|
|
||||||
|
// 输入框:清空时重置列表
|
||||||
|
binding.etSheetInput.run {
|
||||||
|
hint = "输入食材名称或速记码"
|
||||||
|
addTextChangedListener(
|
||||||
|
onTextChanged = { text, _, _, _ -> goodsName = text.toString() },
|
||||||
|
afterTextChanged = { it: Editable? ->
|
||||||
|
if (it.isNullOrBlank()) {
|
||||||
|
list.clear()
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
addOnActionSearchListener { searchGoods(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RecyclerView 初始化及滑动冲突处理
|
||||||
|
binding.recyclerView.run {
|
||||||
|
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
adapter = this@FoodSearchDialog.adapter
|
||||||
|
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
|
||||||
//解决RecyclerView和smartRefreshLayout滑动冲突问题
|
|
||||||
super.onScrolled(rv, dx, dy)
|
super.onScrolled(rv, dx, dy)
|
||||||
|
// 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突
|
||||||
val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top
|
val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top
|
||||||
binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0)
|
binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
binding.refreshLayout.setOnRefreshListener {
|
|
||||||
pageNo = 1
|
binding.refreshLayout.run {
|
||||||
getGoodsList()
|
setEnableRefresh(false)
|
||||||
|
setEnableLoadMore(false)
|
||||||
|
setOnRefreshListener { pageNo = 1; getGoodsList() }
|
||||||
|
setOnLoadMoreListener { getGoodsList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.refreshLayout.setOnLoadMoreListener {
|
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
||||||
getGoodsList()
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) }
|
||||||
}
|
|
||||||
binding.etSheetInput.addTextChangedListener(
|
|
||||||
onTextChanged = { text, start, before, count ->
|
|
||||||
goodsName = text.toString()
|
|
||||||
})
|
|
||||||
binding.ivSearch.setOnClickListener { v ->
|
|
||||||
searchGoods(v)
|
|
||||||
}
|
|
||||||
binding.root.setOnClickListener { v ->
|
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
|
||||||
}
|
|
||||||
binding.etSheetInput.let { v ->
|
|
||||||
v.addOnActionSearchListener {
|
|
||||||
searchGoods(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.refreshLayout.setEnableRefresh(false)
|
|
||||||
binding.refreshLayout.setEnableLoadMore(false)
|
|
||||||
|
|
||||||
if (defGoodsName.isNullOrBlank().not()) {
|
// 若有默认食材名称,自动填充并触发搜索
|
||||||
binding.etSheetInput.let {
|
if (!defGoodsName.isNullOrBlank()) {
|
||||||
it.setText(defGoodsName)
|
binding.etSheetInput.setText(defGoodsName)
|
||||||
searchGoods(it)
|
searchGoods(binding.etSheetInput)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发搜索:校验输入、隐藏键盘、发起请求
|
||||||
|
*/
|
||||||
private fun searchGoods(v: View) {
|
private fun searchGoods(v: View) {
|
||||||
if (goodsName.isNullOrBlank()) {
|
if (goodsName.isNullOrBlank()) {
|
||||||
activity?.toast("请${binding.etSheetInput.hint}")
|
activity.toast("请${binding.etSheetInput.hint}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
@@ -137,109 +117,47 @@ class FoodSearchDialog(
|
|||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v.context, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var pageNo = 1
|
|
||||||
private val pageSize = 50
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 请求食材列表
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
|
||||||
private fun getGoodsList() {
|
private fun getGoodsList() {
|
||||||
// val pathSegmentList = UrlConfig.QUERY_GOODS_LIST.split(delimiters = arrayOf("/"), limit = 1)
|
|
||||||
// val queryParams = mutableMapOf(
|
|
||||||
// "goodsType" to "0",
|
|
||||||
// "canteenId" to BaseApp.canteenId,
|
|
||||||
// "pageNo" to "$pageNo",
|
|
||||||
// "pageSize" to "$pageSize"
|
|
||||||
// )
|
|
||||||
// if (goodsName.isNullOrBlank().not()) {
|
|
||||||
// queryParams.put("name", goodsName!!)
|
|
||||||
// }
|
|
||||||
// val sb = StringBuilder().apply {
|
|
||||||
// append(UrlConfig.QUERY_GOODS_LIST)
|
|
||||||
// append("?")
|
|
||||||
// queryParams.forEach { (key, value) ->
|
|
||||||
// append("$key=$value&")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// sb.deleteCharAt(sb.length - 1)
|
|
||||||
// Log.d(TAG, "getGoodsList: url = $sb")
|
|
||||||
// HttpUtil.get(
|
|
||||||
// url = sb.toString(),
|
|
||||||
// doSuccess = {
|
|
||||||
// val json = it.toJsonString()
|
|
||||||
// Log.d(TAG, "getGoodsList: json=$json")
|
|
||||||
// val recordBean: GoodsRecordBean? = json.toObject<GoodsRecordBean>()
|
|
||||||
// if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
// activity?.toast("暂未搜索到食材信息")
|
|
||||||
// return@get
|
|
||||||
// }
|
|
||||||
// val records = recordBean.records
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// list.clear()
|
|
||||||
// }
|
|
||||||
// list.addAll(records!!)
|
|
||||||
// searchAdapter.notifyDataSetChanged()
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// binding.refreshLayout.finishRefresh(1200)
|
|
||||||
// } else {
|
|
||||||
// binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
// }
|
|
||||||
// val isLoadMoreEnable = records.size >= pageSize
|
|
||||||
// binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
|
||||||
// if (isLoadMoreEnable) {
|
|
||||||
// pageNo++
|
|
||||||
// }
|
|
||||||
// }, doFailure = { code, msg ->
|
|
||||||
// activity?.toast(msg)
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// binding.refreshLayout.finishRefresh(1200)
|
|
||||||
// } else {
|
|
||||||
// binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
val param = mutableMapOf<String, Any>(
|
val param = mutableMapOf<String, Any>(
|
||||||
"goodsType" to "0",
|
"goodsType" to "0",
|
||||||
"placeId" to BaseApp.canteenId,
|
"placeId" to BaseApp.canteenId,
|
||||||
"pageNum" to pageNo,
|
"pageNum" to pageNo,
|
||||||
"pageSize" to pageSize
|
"pageSize" to pageSize
|
||||||
)
|
)
|
||||||
if (goodsName.isNullOrBlank().not()) {
|
if (!goodsName.isNullOrBlank()) {
|
||||||
param.put("goodsName", goodsName!!)
|
param["goodsName"] = goodsName!!
|
||||||
}
|
}
|
||||||
activity?.queryGoodsList(param = param, onSuccess = {
|
activity.queryGoodsList(param = param, onSuccess = {
|
||||||
loadGoodsList(it)
|
loadGoodsList(it)
|
||||||
}, onFailure = { code, msg ->
|
}, onFailure = { _, msg ->
|
||||||
activity?.toast(msg)
|
activity.toast(msg)
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun finishRefresh() {
|
/**
|
||||||
if (pageNo == 1) {
|
* 将返回数据填充到列表
|
||||||
binding.refreshLayout.finishRefresh()
|
*/
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun loadGoodsList(records: MutableList<CookFoodGoodsEntity>?) {
|
private fun loadGoodsList(records: MutableList<CookFoodGoodsEntity>?) {
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
if (records.isNullOrEmpty()) {
|
if (records.isNullOrEmpty()) {
|
||||||
activity?.toast("暂未搜索到食材信息")
|
activity.toast("暂未搜索到食材信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) list.clear()
|
||||||
list.clear()
|
|
||||||
}
|
|
||||||
list.addAll(records)
|
list.addAll(records)
|
||||||
searchAdapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
if (isLoadMoreEnable) {
|
if (isLoadMoreEnable) pageNo++
|
||||||
pageNo++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun finishRefresh() {
|
||||||
|
if (pageNo == 1) binding.refreshLayout.finishRefresh()
|
||||||
|
else binding.refreshLayout.finishLoadMore()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
|||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.Editable
|
|
||||||
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
|
||||||
@@ -38,164 +37,130 @@ import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
|
|||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 调料搜索弹窗
|
* 调料搜索弹窗,继承 BottomSheetDialog 确保只初始化一次
|
||||||
|
* @param activity 宿主 Activity
|
||||||
|
* @param weighIndex 秤的索引
|
||||||
|
* @param weighAddress 秤的地址,用于监听重量和去皮
|
||||||
|
* @param clickName 默认填充的调料名称(可选)
|
||||||
|
* @param onItemSelected 用户点击某一调料时的回调,携带当前重量
|
||||||
*/
|
*/
|
||||||
class SeasoningSearchDialog(
|
class SeasoningSearchDialog(
|
||||||
private var weighIndex: Int,
|
private val activity: BaseActivity,
|
||||||
private var weighAddress: Int,
|
private val weighIndex: Int,
|
||||||
private var clickName: String? = null
|
private val weighAddress: Int,
|
||||||
) {
|
private val clickName: String? = null,
|
||||||
|
private val onItemSelected: (item: SeasoningEntity) -> Unit
|
||||||
|
) : BottomSheetDialog(activity, R.style.BottomSheet) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "BottomDialog2"
|
const val TAG = "BottomDialog2"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var list = mutableListOf<SeasoningEntity>()
|
private val binding = DialogSeasoningSearchBinding.inflate(LayoutInflater.from(activity))
|
||||||
|
private val list = mutableListOf<SeasoningEntity>()
|
||||||
private lateinit var binding: DialogSeasoningSearchBinding
|
private val adapter = SeasoningSearchAdapter(list).apply {
|
||||||
private lateinit var searchAdapter: SeasoningSearchAdapter
|
|
||||||
private var goodsName: String? = null
|
|
||||||
|
|
||||||
private var activity: BaseActivity? = null
|
|
||||||
|
|
||||||
fun show(activity: BaseActivity, callback: (item: SeasoningEntity) -> Unit) {
|
|
||||||
this.activity = activity
|
|
||||||
//直接使用BottomSheetDialog
|
|
||||||
var dialog: BottomSheetDialog? = null
|
|
||||||
val inflater = LayoutInflater.from(activity)
|
|
||||||
binding = DialogSeasoningSearchBinding.inflate(inflater)
|
|
||||||
|
|
||||||
binding.etSheetInput.run {
|
|
||||||
hint = "输入调料名称"
|
|
||||||
addTextChangedListener(afterTextChanged = { it: Editable? ->
|
|
||||||
if (it.isNullOrBlank()) {
|
|
||||||
list.clear()
|
|
||||||
searchAdapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
searchAdapter = SeasoningSearchAdapter(list).apply {
|
|
||||||
setOnItemClickListener { _, _, position ->
|
setOnItemClickListener { _, _, position ->
|
||||||
list[position].isClicked = true
|
list[position].isClicked = true
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
callback(list[position].also { it.useWeight = currentWeight })
|
onItemSelected(list[position].also { it.useWeight = currentWeight })
|
||||||
dialog?.dismiss()
|
dismiss()
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.recyclerView.run {
|
|
||||||
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
private var goodsName: String? = null
|
||||||
adapter = searchAdapter
|
private var currentWeight = 0.0
|
||||||
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
private var pageNo = 1
|
||||||
override fun onScrollStateChanged(rv: RecyclerView, newState: Int) {
|
private val pageSize = 50
|
||||||
super.onScrollStateChanged(rv, newState);
|
|
||||||
|
init {
|
||||||
|
setContentView(binding.root)
|
||||||
|
setCancelable(true)
|
||||||
|
behavior.skipCollapsed = false
|
||||||
|
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
||||||
|
window?.setGravity(Gravity.BOTTOM)
|
||||||
|
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
window?.setWindowAnimations(R.style.DialogSoftInputAnimation)
|
||||||
|
window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||||
|
|
||||||
|
setOnDismissListener {
|
||||||
|
// 弹窗关闭时移除重量监听,避免内存泄漏
|
||||||
|
WeightUtil.removeWeightListener(TAG)
|
||||||
|
activity.hideStatusBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输入框:清空时重置列表
|
||||||
|
binding.etSheetInput.run {
|
||||||
|
hint = "输入调料名称"
|
||||||
|
addTextChangedListener(
|
||||||
|
onTextChanged = { text, _, _, _ -> goodsName = text.toString() },
|
||||||
|
afterTextChanged = {
|
||||||
|
if (it.isNullOrBlank()) {
|
||||||
|
list.clear()
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
addOnActionSearchListener { searchGoods(this) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecyclerView 初始化及滑动冲突处理
|
||||||
|
binding.recyclerView.run {
|
||||||
|
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
adapter = this@SeasoningSearchDialog.adapter
|
||||||
|
addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
|
||||||
//解决RecyclerView和smartRefreshLayout滑动冲突问题
|
|
||||||
super.onScrolled(rv, dx, dy)
|
super.onScrolled(rv, dx, dy)
|
||||||
|
// 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突
|
||||||
val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top
|
val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top
|
||||||
binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0)
|
binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
dialog = BottomSheetDialog(activity, R.style.BottomSheet).apply {
|
|
||||||
setContentView(binding.root)
|
binding.refreshLayout.run {
|
||||||
setCancelable(true)
|
setEnableRefresh(false)
|
||||||
behavior.skipCollapsed = false // 跳过折叠状态
|
setEnableLoadMore(false)
|
||||||
//// behavior.peekHeight = 880.dp
|
setOnRefreshListener { pageNo = 1; getGoodsList() }
|
||||||
//// window?.setLayout(-1, 880.dp)
|
setOnLoadMoreListener { getGoodsList() }
|
||||||
// window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
|
||||||
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
|
|
||||||
//or WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
|
|
||||||
//or WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING // 禁用额外平移
|
|
||||||
window?.setGravity(Gravity.BOTTOM)
|
|
||||||
window?.setLayout(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
)
|
|
||||||
window?.setWindowAnimations(R.style.DialogSoftInputAnimation)
|
|
||||||
window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
|
||||||
show()
|
|
||||||
// val onGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
|
|
||||||
// val r = Rect()
|
|
||||||
// binding.root.getWindowVisibleDisplayFrame(r)
|
|
||||||
// val screenHeight = binding.root.rootView.height
|
|
||||||
// val keyboardHeight = screenHeight - r.bottom
|
|
||||||
//
|
|
||||||
// // 软键盘弹出(高度>200dp)
|
|
||||||
// if (keyboardHeight > 200.dp) {
|
|
||||||
// // 调整 Dialog 底部边距,避开软键盘
|
|
||||||
// val layoutParams = binding.root.layoutParams as ViewGroup.MarginLayoutParams
|
|
||||||
//// layoutParams.bottomMargin = keyboardHeight
|
|
||||||
// layoutParams.bottomMargin = 200.dp
|
|
||||||
// binding.root.layoutParams = layoutParams
|
|
||||||
// } else {
|
|
||||||
// // 软键盘收起,恢复边距
|
|
||||||
// val layoutParams = binding.root.layoutParams as ViewGroup.MarginLayoutParams
|
|
||||||
// layoutParams.bottomMargin = 0
|
|
||||||
// binding.root.layoutParams = layoutParams
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
setOnDismissListener {
|
|
||||||
activity.hideStatusBar()
|
|
||||||
// binding.root.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
|
|
||||||
}
|
|
||||||
// binding.root.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
|
|
||||||
}
|
|
||||||
binding.refreshLayout.setOnRefreshListener {
|
|
||||||
pageNo = 1
|
|
||||||
getGoodsList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.refreshLayout.setOnLoadMoreListener {
|
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
||||||
getGoodsList()
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) }
|
||||||
}
|
|
||||||
binding.etSheetInput.addTextChangedListener(
|
// 去皮按钮
|
||||||
onTextChanged = { text, start, before, count ->
|
|
||||||
goodsName = text.toString()
|
|
||||||
})
|
|
||||||
binding.ivSearch.setOnClickListener { v ->
|
|
||||||
searchGoods(v)
|
|
||||||
}
|
|
||||||
binding.root.setOnClickListener { v ->
|
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
|
||||||
}
|
|
||||||
binding.etSheetInput.let { v ->
|
|
||||||
v.addOnActionSearchListener {
|
|
||||||
searchGoods(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.refreshLayout.setEnableRefresh(false)
|
|
||||||
binding.refreshLayout.setEnableLoadMore(false)
|
|
||||||
binding.tvClear.setOnClickListener {
|
binding.tvClear.setOnClickListener {
|
||||||
Log.d(TAG, "show: weighAddress=$weighAddress")
|
Log.d(TAG, "tareTwo: weighAddress=$weighAddress")
|
||||||
WeightUtil.tareTwo(weighAddress)
|
WeightUtil.tareTwo(weighAddress)
|
||||||
// repeat(14) { num->
|
|
||||||
// Log.d(TAG, "show: num=$num")
|
|
||||||
// WeightUtil.tareTwo(num+1)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听对应秤的重量变化
|
||||||
WeightUtil.addWeightListener(
|
WeightUtil.addWeightListener(
|
||||||
weightKey = TAG,
|
weightKey = TAG,
|
||||||
getWeight = { address, state, weight ->
|
getWeight = { address, _, weight ->
|
||||||
if (weighAddress == address) {
|
if (weighAddress == address) {
|
||||||
this.currentWeight = weight.toDouble()
|
currentWeight = weight.toDouble()
|
||||||
binding.tvWeight.text = getTextSpan(weight)
|
binding.tvWeight.text = getTextSpan(weight)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
binding.tvWeight.text = getTextSpan(0.0)
|
binding.tvWeight.text = getTextSpan(0.0)
|
||||||
|
|
||||||
if (clickName.isNullOrBlank().not()) {
|
// 若有默认调料名称,自动填充并触发搜索
|
||||||
binding.etSheetInput.setText(clickName!!.trim())
|
if (!clickName.isNullOrBlank()) {
|
||||||
|
binding.etSheetInput.setText(clickName.trim())
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发搜索:校验输入、隐藏键盘、发起请求
|
||||||
|
*/
|
||||||
private fun searchGoods(v: View) {
|
private fun searchGoods(v: View) {
|
||||||
if (goodsName.isNullOrBlank()) {
|
if (goodsName.isNullOrBlank()) {
|
||||||
activity?.toast("请${binding.etSheetInput.hint}")
|
activity.toast("请${binding.etSheetInput.hint}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
@@ -203,132 +168,63 @@ class SeasoningSearchDialog(
|
|||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v.context, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var currentWeight = 0.toDouble()
|
|
||||||
private var pageNo = 1
|
|
||||||
private val pageSize = 50
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 请求调料列表
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
|
||||||
private fun getGoodsList() {
|
private fun getGoodsList() {
|
||||||
// val queryParams = mutableMapOf(
|
|
||||||
// "goodsType" to "1",
|
|
||||||
// "canteenId" to BaseApp.canteenId,
|
|
||||||
// "pageNo" to "$pageNo",
|
|
||||||
// "pageSize" to "$pageSize"
|
|
||||||
// )
|
|
||||||
// if (goodsName.isNullOrBlank().not()) {
|
|
||||||
// queryParams.put("name", goodsName!!)
|
|
||||||
// }
|
|
||||||
// val sb = StringBuilder().apply {
|
|
||||||
// append(UrlConfig.QUERY_GOODS_LIST)
|
|
||||||
// append("?")
|
|
||||||
// queryParams.forEach { (key, value) ->
|
|
||||||
// append("$key=$value&")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// sb.deleteCharAt(sb.length - 1)
|
|
||||||
// Log.d(TAG, "getGoodsList: url = $sb")
|
|
||||||
// HttpUtil.get(
|
|
||||||
// url = sb.toString(),
|
|
||||||
// doSuccess = {
|
|
||||||
// val json = it.toJsonString()
|
|
||||||
// Log.d(TAG, "getGoodsList: json=$json")
|
|
||||||
// val recordBean: SeasoningRecordBean? = json.toObject<SeasoningRecordBean>()
|
|
||||||
// if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
// activity?.toast( "暂未搜索到调料信息")
|
|
||||||
// return@get
|
|
||||||
// }
|
|
||||||
// val records = recordBean.records
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// list.clear()
|
|
||||||
// }
|
|
||||||
// list.addAll(records!!)
|
|
||||||
// searchAdapter.notifyDataSetChanged()
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// binding.refreshLayout.finishRefresh(1200)
|
|
||||||
// } else {
|
|
||||||
// binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
// }
|
|
||||||
// val isLoadMoreEnable = records.size >= pageSize
|
|
||||||
// binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
|
||||||
// if (isLoadMoreEnable) {
|
|
||||||
// pageNo++
|
|
||||||
// }
|
|
||||||
// }, doFailure = { code, msg ->
|
|
||||||
// activity?.toast(msg)
|
|
||||||
// if (pageNo == 1) {
|
|
||||||
// binding.refreshLayout.finishRefresh(1200)
|
|
||||||
// } else {
|
|
||||||
// binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
|
|
||||||
val param = mutableMapOf<String, Any>(
|
val param = mutableMapOf<String, Any>(
|
||||||
"goodsType" to "1",
|
"goodsType" to "1",
|
||||||
"placeId" to BaseApp.canteenId,
|
"placeId" to BaseApp.canteenId,
|
||||||
"pageNum" to pageNo,
|
"pageNum" to pageNo,
|
||||||
"pageSize" to pageSize
|
"pageSize" to pageSize
|
||||||
)
|
)
|
||||||
if (goodsName.isNullOrBlank().not()) {
|
if (!goodsName.isNullOrBlank()) {
|
||||||
param.put("goodsName", goodsName!!)
|
param["goodsName"] = goodsName!!
|
||||||
}
|
}
|
||||||
activity?.querySeasoningList(
|
activity.querySeasoningList(param = param, onSuccess = {
|
||||||
param = param,
|
|
||||||
onSuccess = {
|
|
||||||
loadGoodsList(it)
|
loadGoodsList(it)
|
||||||
},
|
}, onFailure = { _, msg ->
|
||||||
onFailure = { code, msg ->
|
activity.toast(msg)
|
||||||
activity?.toast(msg)
|
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将返回数据填充到列表
|
||||||
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun loadGoodsList(records: MutableList<SeasoningEntity>?) {
|
private fun loadGoodsList(records: MutableList<SeasoningEntity>?) {
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
if (records.isNullOrEmpty()) {
|
if (records.isNullOrEmpty()) {
|
||||||
activity?.toast("暂未搜索到调料信息")
|
activity.toast("暂未搜索到调料信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) list.clear()
|
||||||
list.clear()
|
|
||||||
}
|
|
||||||
list.addAll(records)
|
list.addAll(records)
|
||||||
searchAdapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
if (isLoadMoreEnable) {
|
if (isLoadMoreEnable) pageNo++
|
||||||
pageNo++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun finishRefresh() {
|
private fun finishRefresh() {
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) binding.refreshLayout.finishRefresh()
|
||||||
binding.refreshLayout.finishRefresh()
|
else binding.refreshLayout.finishLoadMore()
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成重量显示的富文本:数值大字加粗,单位小字灰色
|
||||||
|
*/
|
||||||
fun getTextSpan(weight: Double): SpannableStringBuilder {
|
fun getTextSpan(weight: Double): SpannableStringBuilder {
|
||||||
var topWeight = "$weight"
|
val topWeight = if (weight >= 1000) "${(weight / 1000).roundedDecimalPlace(3)}" else "$weight"
|
||||||
var bottomUnit = "克"
|
val bottomUnit = if (weight >= 1000) "千克" else "克"
|
||||||
if (weight >= 1000) {
|
|
||||||
topWeight = "${(weight / 1000).roundedDecimalPlace(3)}"
|
|
||||||
bottomUnit = "千克"
|
|
||||||
}
|
|
||||||
return buildSpannableString {
|
return buildSpannableString {
|
||||||
appendText(
|
appendText(
|
||||||
topWeight,
|
topWeight,
|
||||||
ForegroundColorSpan("#000000".toColorInt()),
|
ForegroundColorSpan("#000000".toColorInt()),
|
||||||
StyleSpan(Typeface.BOLD),
|
StyleSpan(Typeface.BOLD),
|
||||||
AbsoluteSizeSpan(72, true),
|
AbsoluteSizeSpan(72, true),
|
||||||
LineHeightSpan { text, start, end, spanstartv, v, fm ->
|
LineHeightSpan { _, _, _, _, _, fm -> fm.descent += 10.dp }
|
||||||
fm.descent += 10.dp // 增加行间距
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
append("\n")
|
append("\n")
|
||||||
appendText(
|
appendText(
|
||||||
@@ -339,6 +235,3 @@ class SeasoningSearchDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -111,16 +111,16 @@ object ScaleServiceManager {
|
|||||||
client.connect(remoteId, host, port)
|
client.connect(remoteId, host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
// mDNS 发现:发现子设备 → 建立 WebSocket 连接;设备离线 → 断开连接并清除数据
|
// mDNS 发现:发现子设备 → 建立 WebSocket 连接;设备离线 → 仅清除 UDP 缓存,WebSocket 层自行重连
|
||||||
mdnsDiscovery = MdnsDiscoveryManager(context).also { discovery ->
|
mdnsDiscovery = MdnsDiscoveryManager(context).also { discovery ->
|
||||||
discovery.onDeviceFound = { remoteId, host, port ->
|
discovery.onDeviceFound = { remoteId, host, port ->
|
||||||
onDeviceFound(remoteId, host, port)
|
onDeviceFound(remoteId, host, port)
|
||||||
}
|
}
|
||||||
discovery.onDeviceLost = { remoteId ->
|
discovery.onDeviceLost = { remoteId ->
|
||||||
Log.d(TAG, "子设备离线 $remoteId, 断开连接并清除数据")
|
// mDNS 抖动不永久断开,WebSocket 层会持续重连直到网络恢复
|
||||||
client.disconnect(remoteId)
|
// 仅清除 UDP 缓存,确保 UDP 重新发现时能再次触发 onDeviceFound
|
||||||
aggregator?.removeDevice(remoteId)
|
|
||||||
udpReceiver?.removeDevice(remoteId)
|
udpReceiver?.removeDevice(remoteId)
|
||||||
|
Log.d(TAG, "子设备 mDNS 离线: $remoteId, 保持 WebSocket 重连")
|
||||||
}
|
}
|
||||||
discovery.startDiscovery()
|
discovery.startDiscovery()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,10 +100,10 @@ class ScaleWebSocketClient {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 指数退避重连
|
* 指数退避重连
|
||||||
|
* 入口不拦截 removedDevices,仅在延迟任务执行前检查,
|
||||||
|
* 确保 disconnect() 后已入队的任务不执行,但新断线事件始终能进入重连流程
|
||||||
*/
|
*/
|
||||||
private fun scheduleReconnect(deviceId: String, host: String, port: Int) {
|
private fun scheduleReconnect(deviceId: String, host: String, port: Int) {
|
||||||
if (removedDevices.contains(deviceId)) return
|
|
||||||
|
|
||||||
val delay = reconnectDelays[deviceId] ?: RECONNECT_BASE_MS
|
val delay = reconnectDelays[deviceId] ?: RECONNECT_BASE_MS
|
||||||
Log.d(TAG, "将在 ${delay}ms 后重连子设备: $deviceId")
|
Log.d(TAG, "将在 ${delay}ms 后重连子设备: $deviceId")
|
||||||
|
|
||||||
|
|||||||
@@ -251,10 +251,11 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
||||||
// val seasoningEntity = list.first{it.sort == sort}
|
// val seasoningEntity = list.first{it.sort == sort}
|
||||||
SeasoningSearchDialog(
|
SeasoningSearchDialog(
|
||||||
|
activity = this,
|
||||||
weighIndex = sort,
|
weighIndex = sort,
|
||||||
weighAddress = currentAddress,
|
weighAddress = currentAddress,
|
||||||
clickName = entity.goodsName
|
clickName = entity.goodsName
|
||||||
).show(this) { item ->
|
) { item ->
|
||||||
syncItem(entity, item)
|
syncItem(entity, item)
|
||||||
//3-调料
|
//3-调料
|
||||||
entity.materialType = 3
|
entity.materialType = 3
|
||||||
@@ -265,7 +266,7 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
TextCellAdapter.loadLayout(frameLayout, entity)
|
||||||
}
|
}
|
||||||
}
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncItem(oldItem: SeasoningEntity, newItem: SeasoningEntity) {
|
private fun syncItem(oldItem: SeasoningEntity, newItem: SeasoningEntity) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
@@ -75,6 +76,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
binding.tvDishPartWeight.text = "${weight}"
|
binding.tvDishPartWeight.text = "${weight}"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
addBackKeyListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setTitleBar() {
|
private fun setTitleBar() {
|
||||||
@@ -91,7 +93,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
}, backAction = {
|
}, backAction = {
|
||||||
it.visible()
|
it.visible()
|
||||||
it.setOnClickListener {
|
it.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -110,19 +112,21 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
/**
|
||||||
@SuppressLint("GestureBackNavigation")
|
* 监听返回键
|
||||||
@Deprecated("Deprecated in Java")
|
*/
|
||||||
override fun onBackPressed() {
|
fun addBackKeyListener() {
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
if (list.isEmpty().not()) {
|
if (list.isEmpty().not()) {
|
||||||
//说明有新增的食材
|
//说明有新增的食材
|
||||||
saveDataRemindDialog()
|
saveDataRemindDialog()
|
||||||
return
|
return@addCallback
|
||||||
}
|
}
|
||||||
if (pageFrom == HOME) {
|
if (pageFrom == HOME) {
|
||||||
startActivity<SamplingListActivity>()
|
startActivity<SamplingListActivity>()
|
||||||
}
|
}
|
||||||
super.onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveDataRemindDialog() {
|
private fun saveDataRemindDialog() {
|
||||||
@@ -276,11 +280,14 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
|
|
||||||
private fun searchDishType() {
|
private fun searchDishType() {
|
||||||
val inputText = binding.etInputDishType.text.toString().trim()
|
val inputText = binding.etInputDishType.text.toString().trim()
|
||||||
FoodSearchDialog(defGoodsName = inputText).show(this@DishSamplingActivity) { item ->
|
FoodSearchDialog(
|
||||||
|
activity = this@DishSamplingActivity,
|
||||||
|
defGoodsName = inputText
|
||||||
|
) { item ->
|
||||||
val filterResult = list.firstOrNull { it.goodsName == item.goodsName }
|
val filterResult = list.firstOrNull { it.goodsName == item.goodsName }
|
||||||
if (filterResult != null) {
|
if (filterResult != null) {
|
||||||
toast("不允许重复添加同一食材")
|
toast("不允许重复添加同一食材")
|
||||||
return@show
|
return@FoodSearchDialog
|
||||||
}
|
}
|
||||||
binding.etInputDishType.run {
|
binding.etInputDishType.run {
|
||||||
setText(item.goodsName)
|
setText(item.goodsName)
|
||||||
@@ -297,7 +304,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
// TODO: 待定
|
// TODO: 待定
|
||||||
//allEdible = item.allEdible
|
//allEdible = item.allEdible
|
||||||
}
|
}
|
||||||
}
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
@@ -48,6 +49,7 @@ class HomeActivity : BaseActivity() {
|
|||||||
BaseApp.canteenId = "0"
|
BaseApp.canteenId = "0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onBackPressedDispatcher.addCallback(this) {}
|
||||||
// binding.radioGroup.check(R.id.radioZk)
|
// binding.radioGroup.check(R.id.radioZk)
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
// HttpUtil.getAppToken()
|
// HttpUtil.getAppToken()
|
||||||
@@ -164,12 +166,4 @@ class HomeActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
@SuppressLint("GestureBackNavigation", "MissingSuperCall")
|
|
||||||
override fun onBackPressed() {
|
|
||||||
//super.onBackPressed()
|
|
||||||
//当前页面不允许返回
|
|
||||||
//dialog = toast("不允许返回操作")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import android.os.Bundle
|
|||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.animation.RotateAnimation
|
import android.view.animation.RotateAnimation
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -247,11 +247,9 @@ class InitActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addBackKeyListener() {
|
private fun addBackKeyListener() {
|
||||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
override fun handleOnBackPressed() {
|
|
||||||
// 禁用返回键,不执行任何操作
|
// 禁用返回键,不执行任何操作
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,9 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@@ -21,6 +23,28 @@ import com.shuwei.dish.match.utils.ext.dp
|
|||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/** 根据列数计算正方形格子边长(屏幕可用宽度 / 列数) */
|
||||||
|
private fun android.content.Context.cellSize(columns: Int): Int {
|
||||||
|
val screenWidth = resources.displayMetrics.widthPixels
|
||||||
|
// 减去左右 padding(16dp * 2)和格子间距(2dp * 2 * columns)
|
||||||
|
val usable = screenWidth - 32.dp - columns * 4.dp
|
||||||
|
return usable / columns
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val DEVICE_ID_2 = "8fc2ab34-2137-3112-acca-f884ea8736d4" // 2个秤
|
||||||
|
private const val DEVICE_ID_22 = "a46fa55c-113c-3511-bb1f-41e5eff77c4b" // 22个秤
|
||||||
|
private const val DEVICE_ID_18 = "1038da9f-c6eb-326e-a1d9-d6d3af978b22" // 18个秤
|
||||||
|
private const val DEVICE_ID_1 = "7cc0f6ea-f13d-3013-a867-fc998eb554ac" // 1个秤
|
||||||
|
|
||||||
|
/** 22个秤的显示顺序 */
|
||||||
|
private val SCALE_ORDER_22 = listOf(20,22,19,21,6,12,18,5,11,17,4,10,16,3,9,15,2,8,14,1,7,13)
|
||||||
|
|
||||||
|
/** 18个秤的显示顺序 */
|
||||||
|
private val SCALE_ORDER_18 = listOf(6,5,4,3,2,1, 12,11,10,9,8,7, 18,17,16,15,14,13)
|
||||||
|
|
||||||
|
/** 设备显示顺序,第一个为本机设备号,其余按指定顺序排列,不在列表中的设备追加到末尾 */
|
||||||
|
private val deviceOrder = listOf(DEVICE_ID_2, DEVICE_ID_22, DEVICE_ID_18, DEVICE_ID_1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主设备秤数据总览页面(仅 MASTER 角色显示)
|
* 主设备秤数据总览页面(仅 MASTER 角色显示)
|
||||||
* 聚合展示所有设备(本机 + 远端子设备)的实时秤数据
|
* 聚合展示所有设备(本机 + 远端子设备)的实时秤数据
|
||||||
@@ -54,7 +78,7 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
|
|
||||||
binding.ivMasterBack.setOnClickListener { finish() }
|
binding.ivMasterBack.setOnClickListener { finish() }
|
||||||
binding.rvScaleList.layoutManager = LinearLayoutManager(this)
|
binding.rvScaleList.layoutManager = LinearLayoutManager(this)
|
||||||
binding.rvScaleList.itemAnimator = null // 关闭默认动画,避免数据频繁更新时出现闪烁错乱
|
binding.rvScaleList.itemAnimator = null
|
||||||
binding.rvScaleList.adapter = adapter
|
binding.rvScaleList.adapter = adapter
|
||||||
|
|
||||||
observeScaleData()
|
observeScaleData()
|
||||||
@@ -66,17 +90,16 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private fun observeScaleData() {
|
private fun observeScaleData() {
|
||||||
val flow = ScaleServiceManager.allScales ?: return
|
val flow = ScaleServiceManager.allScales ?: return
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
flow.collectLatest { scaleMap ->
|
flow.collectLatest { scaleMap ->
|
||||||
// 按 deviceId 分组,本机设备排最前,其余按 deviceId 排序
|
|
||||||
val localId = com.shuwei.dish.match.base.GlobalData.deviceId
|
val localId = com.shuwei.dish.match.base.GlobalData.deviceId
|
||||||
// 本机 IP 实时读取,避免 App 启动时网络未就绪导致缓存为空
|
|
||||||
val localIp = NetworkUtil.getLocalIpAddress(this@MasterScaleActivity)
|
val localIp = NetworkUtil.getLocalIpAddress(this@MasterScaleActivity)
|
||||||
val groups = scaleMap.values
|
val groups = scaleMap.values
|
||||||
.groupBy { it.deviceId }
|
.groupBy { it.deviceId }
|
||||||
.entries
|
.entries
|
||||||
.sortedWith(compareBy({ if (it.key == localId) 0 else 1 }, { it.key }))
|
.sortedWith(compareBy { idx ->
|
||||||
|
deviceOrder.indexOf(idx.key).let { if (it == -1) Int.MAX_VALUE else it }
|
||||||
|
})
|
||||||
.map { (deviceId, scales) ->
|
.map { (deviceId, scales) ->
|
||||||
DeviceGroup(
|
DeviceGroup(
|
||||||
deviceId = deviceId,
|
deviceId = deviceId,
|
||||||
@@ -124,24 +147,159 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
holder.binding.tvDeviceLabel.text = "设备:${group.deviceId}"
|
holder.binding.tvDeviceLabel.text = "设备:${group.deviceId}"
|
||||||
holder.binding.tvDeviceIp.text = "IP:${group.ip.ifEmpty { "未知" }}"
|
holder.binding.tvDeviceIp.text = "IP:${group.ip.ifEmpty { "未知" }}"
|
||||||
|
|
||||||
// 清空旧秤行,重新填充
|
|
||||||
val container: LinearLayout = holder.binding.llScaleContainer
|
val container: LinearLayout = holder.binding.llScaleContainer
|
||||||
container.removeAllViews()
|
container.removeAllViews()
|
||||||
|
|
||||||
group.scales.forEach { scale ->
|
// 根据设备号选择不同的网格布局策略
|
||||||
|
when (group.deviceId) {
|
||||||
|
DEVICE_ID_22 -> buildLayout22(container, group.scales)
|
||||||
|
DEVICE_ID_18 -> buildLayout18(container, group.scales)
|
||||||
|
DEVICE_ID_2 -> buildLayout2(container, group.scales)
|
||||||
|
else -> buildLayoutDefault(container, group.scales)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 22个秤布局:8列,前2列权重1.5(大格子),后6列权重1.0(小格子)
|
||||||
|
* 显示顺序:[20,22,19,21,6,12,18,5,11,17,4,10,16,3,9,15,2,8,14,1,7,13]
|
||||||
|
*/
|
||||||
|
private fun buildLayout22(container: LinearLayout, scales: List<ScaleData>) {
|
||||||
|
val margin = 2.dp
|
||||||
|
val usable = resources.displayMetrics.widthPixels - 32.dp
|
||||||
|
val leftColW = (usable * 1.5f / 9f).toInt()
|
||||||
|
val rightColW = (usable * 1.0f / 9f).toInt()
|
||||||
|
val largeCellSize = leftColW - margin * 2
|
||||||
|
val smallCellSize = rightColW - margin * 2
|
||||||
|
|
||||||
|
// 按指定顺序重排
|
||||||
|
val scaleByAddress = scales.associateBy { it.address }
|
||||||
|
val sorted = SCALE_ORDER_22.map { scaleByAddress[it] }
|
||||||
|
|
||||||
|
val outerRow = LinearLayout(container.context).apply {
|
||||||
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var index = 0
|
||||||
|
// 前2列:权重1.5,每列2个大格子(正方形)
|
||||||
|
repeat(2) { colIdx ->
|
||||||
|
val col = LinearLayout(container.context).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.5f)
|
||||||
|
}
|
||||||
|
repeat(2) { rowIdx ->
|
||||||
|
val cell = makeScaleCellFixed(sorted.getOrNull(index++), largeCellSize, largeCellSize, margin)
|
||||||
|
// 两列中间水平间距翻倍(第1列右边距、第2列左边距),列内两格子中间垂直间距翻倍,外侧保持不变
|
||||||
|
(cell.layoutParams as? LinearLayout.LayoutParams)?.apply {
|
||||||
|
bottomMargin = if (rowIdx == 0) margin * 2 else margin
|
||||||
|
topMargin = if (rowIdx == 1) margin * 2 else margin
|
||||||
|
rightMargin = if (colIdx == 0) margin * 2 else margin
|
||||||
|
leftMargin = if (colIdx == 1) margin * 2 else margin
|
||||||
|
}
|
||||||
|
col.addView(cell)
|
||||||
|
}
|
||||||
|
outerRow.addView(col)
|
||||||
|
}
|
||||||
|
// 后6列:权重1.0,每列3个小格子(正方形)
|
||||||
|
repeat(6) {
|
||||||
|
val col = LinearLayout(container.context).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f)
|
||||||
|
}
|
||||||
|
repeat(3) {
|
||||||
|
col.addView(makeScaleCellFixed(sorted.getOrNull(index++), smallCellSize, smallCellSize, margin))
|
||||||
|
}
|
||||||
|
outerRow.addView(col)
|
||||||
|
}
|
||||||
|
container.addView(outerRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建固定宽高的秤格子(用于22格子布局,宽高可独立指定)
|
||||||
|
* @param scale 秤数据
|
||||||
|
* @param width 内容宽度(px)
|
||||||
|
* @param height 内容高度(px)
|
||||||
|
* @param margin 外边距(px)
|
||||||
|
*/
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun makeScaleCellFixed(scale: ScaleData?, width: Int, height: Int, margin: Int): View {
|
||||||
|
val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height)
|
||||||
|
.also { it.setMargins(margin, margin, margin, margin) }
|
||||||
|
|
||||||
|
return LinearLayout(this).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = lp
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
setPadding(4.dp, 2.dp, 4.dp, 2.dp)
|
||||||
|
setBackgroundResource(R.drawable.shape_scale_cell)
|
||||||
|
if (scale != null) {
|
||||||
val stateStr = when (scale.state) {
|
val stateStr = when (scale.state) {
|
||||||
WeightUtil.STATE_STABLE -> "稳定"
|
WeightUtil.STATE_STABLE -> "稳定"
|
||||||
WeightUtil.STATE_UNSTABLE -> "不稳定"
|
WeightUtil.STATE_UNSTABLE -> "不稳定"
|
||||||
WeightUtil.STATE_OVER_WEIGHT -> "超量"
|
WeightUtil.STATE_OVER_WEIGHT -> "超量"
|
||||||
else -> "${scale.state}"
|
else -> "${scale.state}"
|
||||||
}
|
}
|
||||||
// 每行:秤编号 重量 状态
|
val baseSize = (height / resources.displayMetrics.density).toInt()
|
||||||
val row = LinearLayout(holder.itemView.context).apply {
|
val addrSp = (baseSize * 0.16f).coerceIn(9f, 14f).toInt()
|
||||||
|
val weightSp = (baseSize * 0.22f).coerceIn(12f, 20f).toInt()
|
||||||
|
val stateSp = (baseSize * 0.14f).coerceIn(8f, 12f).toInt()
|
||||||
|
addView(makeCellTextView("秤${scale.address}", addrSp))
|
||||||
|
addView(makeCellTextView("${scale.weight}g", weightSp, bold = true))
|
||||||
|
addView(makeCellTextView(stateStr, stateSp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 18个秤布局:6列3行,第1行小格子,第2-3行大格子
|
||||||
|
* 显示顺序:[6,5,4,3,2,1, 12,11,10,9,8,7, 18,17,16,15,14,13]
|
||||||
|
*/
|
||||||
|
private fun buildLayout18(container: LinearLayout, scales: List<ScaleData>) {
|
||||||
|
val cellSize = container.context.cellSize(6)
|
||||||
|
// 按指定顺序重排(address 从1开始,转为0-based index取值)
|
||||||
|
val scaleByAddress = scales.associateBy { it.address }
|
||||||
|
val sorted = SCALE_ORDER_18.map { scaleByAddress[it] }
|
||||||
|
|
||||||
|
var index = 0
|
||||||
|
// 第1行:增大 margin 使格子看起来更小
|
||||||
|
val row1 = makeRowLayout(container)
|
||||||
|
repeat(6) { row1.addView(makeScaleCell(sorted.getOrNull(index++), cellSize, inHorizontalRow = true, margin = 8.dp)) }
|
||||||
|
container.addView(row1)
|
||||||
|
repeat(2) {
|
||||||
|
val row = makeRowLayout(container)
|
||||||
|
repeat(6) { row.addView(makeScaleCell(sorted.getOrNull(index++), cellSize, inHorizontalRow = true)) }
|
||||||
|
container.addView(row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 2个秤布局:1行2列 */
|
||||||
|
private fun buildLayout2(container: LinearLayout, scales: List<ScaleData>) {
|
||||||
|
val cellSize = container.context.cellSize(2)
|
||||||
|
val row = makeRowLayout(container)
|
||||||
|
scales.take(2).forEach { row.addView(makeScaleCell(it, cellSize, inHorizontalRow = true)) }
|
||||||
|
container.addView(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 默认布局:逐行展示,每行加格子背景 */
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun buildLayoutDefault(container: LinearLayout, scales: List<ScaleData>) {
|
||||||
|
scales.forEach { scale ->
|
||||||
|
val stateStr = when (scale.state) {
|
||||||
|
WeightUtil.STATE_STABLE -> "稳定"
|
||||||
|
WeightUtil.STATE_UNSTABLE -> "不稳定"
|
||||||
|
WeightUtil.STATE_OVER_WEIGHT -> "超量"
|
||||||
|
else -> "${scale.state}"
|
||||||
|
}
|
||||||
|
val row = LinearLayout(container.context).apply {
|
||||||
orientation = LinearLayout.HORIZONTAL
|
orientation = LinearLayout.HORIZONTAL
|
||||||
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
layoutParams = LinearLayout.LayoutParams(
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
LinearLayout.LayoutParams.MATCH_PARENT, 120.dp
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
).also { it.setMargins(2.dp, 4.dp, 2.dp, 4.dp) }
|
||||||
).also { it.topMargin = 4.dp }
|
setPadding(30.dp, 0, 0, 0)
|
||||||
|
setBackgroundResource(R.drawable.shape_scale_cell)
|
||||||
}
|
}
|
||||||
row.addView(makeTextView("秤 ${scale.address}", 22, weight = 1f))
|
row.addView(makeTextView("秤 ${scale.address}", 22, weight = 1f))
|
||||||
row.addView(makeTextView("${scale.weight} g", 26, bold = true, weight = 2f))
|
row.addView(makeTextView("${scale.weight} g", 26, bold = true, weight = 2f))
|
||||||
@@ -150,22 +308,86 @@ class MasterScaleActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 创建秤行内的 TextView */
|
/** 创建横向行容器 */
|
||||||
private fun makeTextView(
|
private fun makeRowLayout(parent: ViewGroup): LinearLayout =
|
||||||
text: String,
|
LinearLayout(parent.context).apply {
|
||||||
spSize: Int,
|
orientation = LinearLayout.HORIZONTAL
|
||||||
bold: Boolean = false,
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
weight: Float = 1f
|
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
): TextView = TextView(this@MasterScaleActivity).apply {
|
|
||||||
this.text = text
|
|
||||||
textSize = spSize.toFloat()
|
|
||||||
if (bold) setTypeface(null, android.graphics.Typeface.BOLD)
|
|
||||||
setTextColor(
|
|
||||||
if (bold) getColor(R.color.home_title)
|
|
||||||
else getColor(R.color.home_sub_title)
|
|
||||||
)
|
)
|
||||||
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, weight)
|
}
|
||||||
|
|
||||||
|
/** 创建纵向列容器(等宽分配) */
|
||||||
|
private fun makeColumnLayout(parent: ViewGroup): LinearLayout =
|
||||||
|
LinearLayout(parent.context).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建单个秤格子视图
|
||||||
|
* @param scale 秤数据,为 null 时显示空格子占位
|
||||||
|
* @param cellSize 格子边长(px),宽高相等实现正方形效果
|
||||||
|
* @param inHorizontalRow 是否处于横向行中(true=按权重分配宽度,false=宽度撑满)
|
||||||
|
* @param margin 格子外边距(px),增大可让格子视觉上更小
|
||||||
|
*/
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
private fun makeScaleCell(scale: ScaleData?, cellSize: Int, inHorizontalRow: Boolean, margin: Int = 2.dp): View {
|
||||||
|
// 实际格子内容高度 = 格子分配宽度 - 左右 margin,保证宽高一致接近正方形
|
||||||
|
val contentSize = cellSize - margin * 2
|
||||||
|
val lp = if (inHorizontalRow) {
|
||||||
|
LinearLayout.LayoutParams(0, contentSize, 1f)
|
||||||
|
} else {
|
||||||
|
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, contentSize)
|
||||||
|
}.also { it.setMargins(margin, margin, margin, margin) }
|
||||||
|
|
||||||
|
return LinearLayout(this).apply {
|
||||||
|
orientation = LinearLayout.VERTICAL
|
||||||
|
layoutParams = lp
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
setPadding(4.dp, 2.dp, 4.dp, 2.dp)
|
||||||
|
setBackgroundResource(R.drawable.shape_scale_cell)
|
||||||
|
if (scale != null) {
|
||||||
|
val stateStr = when (scale.state) {
|
||||||
|
WeightUtil.STATE_STABLE -> "稳定"
|
||||||
|
WeightUtil.STATE_UNSTABLE -> "不稳定"
|
||||||
|
WeightUtil.STATE_OVER_WEIGHT -> "超量"
|
||||||
|
else -> "${scale.state}"
|
||||||
|
}
|
||||||
|
// 字号根据格子尺寸自适应(格子越小字越小)
|
||||||
|
val baseSize = (cellSize / resources.displayMetrics.density).toInt()
|
||||||
|
val addrSp = (baseSize * 0.16f).coerceIn(9f, 14f).toInt()
|
||||||
|
val weightSp = (baseSize * 0.22f).coerceIn(12f, 20f).toInt()
|
||||||
|
val stateSp = (baseSize * 0.14f).coerceIn(8f, 12f).toInt()
|
||||||
|
addView(makeCellTextView("秤${scale.address}", addrSp))
|
||||||
|
addView(makeCellTextView("${scale.weight}g", weightSp, bold = true))
|
||||||
|
addView(makeCellTextView(stateStr, stateSp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 创建格子内居中 TextView */
|
||||||
|
private fun makeCellTextView(text: String, spSize: Int, bold: Boolean = false): TextView =
|
||||||
|
TextView(this).apply {
|
||||||
|
this.text = text
|
||||||
|
textSize = spSize.toFloat()
|
||||||
|
if (bold) setTypeface(null, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(if (bold) getColor(R.color.home_title) else getColor(R.color.home_sub_title))
|
||||||
|
layoutParams = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
gravity = Gravity.CENTER
|
||||||
|
includeFontPadding = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 创建默认布局行内的 TextView */
|
||||||
|
private fun makeTextView(
|
||||||
|
text: String, spSize: Int, bold: Boolean = false, weight: Float = 1f
|
||||||
|
): TextView = TextView(this).apply {
|
||||||
|
this.text = text
|
||||||
|
textSize = spSize.toFloat()
|
||||||
|
if (bold) setTypeface(null, android.graphics.Typeface.BOLD)
|
||||||
|
setTextColor(if (bold) getColor(R.color.home_title) else getColor(R.color.home_sub_title))
|
||||||
|
layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, weight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.shuwei.dish.match.ui
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -20,7 +19,7 @@ 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
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
||||||
import com.shuwei.dish.match.objbox.FoodModule
|
import com.shuwei.dish.match.objbox.FoodModule
|
||||||
@@ -41,6 +40,7 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
class PrepareCookActivity : BaseActivity() {
|
class PrepareCookActivity : BaseActivity() {
|
||||||
@@ -48,6 +48,8 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
companion object {
|
companion object {
|
||||||
const val TAG = "CookActivity"
|
const val TAG = "CookActivity"
|
||||||
const val FOOD_ITEM = "foodItem"
|
const val FOOD_ITEM = "foodItem"
|
||||||
|
const val WEIGHT_CHANGE_VALUE = 5
|
||||||
|
const val WEIGHT_RECOGNIZE_VALUE = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivityPrepareCookBinding
|
private lateinit var binding: ActivityPrepareCookBinding
|
||||||
@@ -76,12 +78,13 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}, backAction = {
|
}, backAction = {
|
||||||
it.setOnClickListener {
|
it.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
|
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
|
||||||
binding.tvDishName.text = food?.foodName ?: ""
|
binding.tvDishName.text = food?.foodName ?: ""
|
||||||
addViewClickListener()
|
addViewClickListener()
|
||||||
|
addBackKeyListener()
|
||||||
|
|
||||||
initCamera(binding.flCameraContainer)
|
initCamera(binding.flCameraContainer)
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
@@ -126,6 +129,9 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加重量信息到食材数据
|
||||||
|
*/
|
||||||
private fun addWeight() {
|
private fun addWeight() {
|
||||||
if (clickIndex == -1) {
|
if (clickIndex == -1) {
|
||||||
toast("请选择菜品构成")
|
toast("请选择菜品构成")
|
||||||
@@ -153,17 +159,20 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val isTakingPhoto = AtomicBoolean(false)
|
private val isTakingPhoto = AtomicBoolean(false)
|
||||||
|
private var lastWeight = 0.0
|
||||||
|
private var currentWeight = 0.0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重量稳定时触发菜品识别
|
* 重量稳定时触发菜品识别
|
||||||
* @param weight 当前稳定重量
|
* @param weight 当前稳定重量
|
||||||
*/
|
*/
|
||||||
private fun recognizeFood(weight: Double) {
|
private fun recognizeFood(weight: Double) {
|
||||||
if (weight < 10) {
|
this.currentWeight = weight
|
||||||
|
if (weight < WEIGHT_RECOGNIZE_VALUE) {
|
||||||
if (recognizeDialog.isShowing) recognizeDialog.dismiss()
|
if (recognizeDialog.isShowing) recognizeDialog.dismiss()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (isTakingPhoto.get() || recognizeDialog.isShowing) return
|
if (isTakingPhoto.get() || recognizeDialog.isShowing || abs(lastWeight - weight) <= WEIGHT_CHANGE_VALUE) return
|
||||||
isTakingPhoto.set(true)
|
isTakingPhoto.set(true)
|
||||||
cameraUtils.takePhoto(
|
cameraUtils.takePhoto(
|
||||||
succCallback = cameraSuccessCallback,
|
succCallback = cameraSuccessCallback,
|
||||||
@@ -171,12 +180,14 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFood() {
|
/**
|
||||||
FoodSearchDialog().show(this) { item ->
|
* 菜品选择回调
|
||||||
|
*/
|
||||||
|
private val foodSelectCallback: (CookFoodGoodsEntity) -> Unit = foodSelectCallback@{ item ->
|
||||||
val filterResult = list.firstOrNull { it.goodsId == item.goodsId }
|
val filterResult = list.firstOrNull { it.goodsId == item.goodsId }
|
||||||
if (filterResult != null) {
|
if (filterResult != null) {
|
||||||
toast("不允许重复添加同一食材")
|
toast("不允许重复添加同一食材")
|
||||||
return@show
|
return@foodSelectCallback
|
||||||
}
|
}
|
||||||
list.add(CookFoodGoodsEntity().apply {
|
list.add(CookFoodGoodsEntity().apply {
|
||||||
goodsId = item.goodsId
|
goodsId = item.goodsId
|
||||||
@@ -185,9 +196,15 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
isNewDishType = true
|
isNewDishType = true
|
||||||
isOriginalData = false
|
isOriginalData = false
|
||||||
})
|
})
|
||||||
onItemClick(list.size - 1)
|
onFoodItemClick(list.size - 1)
|
||||||
binding.rvDishPartList.smoothScrollToPosition(list.size - 1)
|
binding.rvDishPartList.smoothScrollToPosition(list.size - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加食材
|
||||||
|
*/
|
||||||
|
private fun addFood() {
|
||||||
|
FoodSearchDialog(activity = this, onItemSelected = foodSelectCallback).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openSubmitPage() {
|
private fun openSubmitPage() {
|
||||||
@@ -289,24 +306,24 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
private var firstReqSize = 0
|
private var firstReqSize = 0
|
||||||
private val list = mutableListOf<CookFoodGoodsEntity>()
|
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||||
private val recognizeDialog by lazy {
|
private val recognizeDialog by lazy {
|
||||||
FoodRecognizeDialog(this) { item ->
|
FoodRecognizeDialog(
|
||||||
// TODO: 处理识别结果选中
|
activity = this,
|
||||||
}
|
onDismiss = { isTakingPhoto.set(false) },
|
||||||
.apply {
|
onItemSelected = foodSelectCallback
|
||||||
setOnDismissListener {
|
)
|
||||||
isTakingPhoto.set(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private val dishPartAdapter by lazy {
|
private val dishPartAdapter by lazy {
|
||||||
DishPartAdapter(list).apply {
|
DishPartAdapter(list).apply {
|
||||||
setOnItemClickListener { _, _, positon ->
|
setOnItemClickListener { _, _, positon ->
|
||||||
onItemClick(positon)
|
onFoodItemClick(positon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onItemClick(positon: Int) {
|
/**
|
||||||
|
* 菜品列表item点击
|
||||||
|
*/
|
||||||
|
private fun onFoodItemClick(positon: Int) {
|
||||||
this@PrepareCookActivity.clickIndex = positon
|
this@PrepareCookActivity.clickIndex = positon
|
||||||
list[clickIndex].let { it ->
|
list[clickIndex].let { it ->
|
||||||
binding.tvDishShowName.run {
|
binding.tvDishShowName.run {
|
||||||
@@ -349,6 +366,9 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
|
|
||||||
private var clickIndex = -1
|
private var clickIndex = -1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RecyclerView初始化
|
||||||
|
*/
|
||||||
private fun initRecyclerView() {
|
private fun initRecyclerView() {
|
||||||
binding.rvDishPartList.run {
|
binding.rvDishPartList.run {
|
||||||
layoutManager =
|
layoutManager =
|
||||||
@@ -393,30 +413,23 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
cameraUtils.setPreviewController(previewBinding.previewView)
|
cameraUtils.setPreviewController(previewBinding.previewView)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
/**
|
||||||
@SuppressLint("GestureBackNavigation")
|
* 注册返回键监听,替代已废弃的 onBackPressed()
|
||||||
@Deprecated("Deprecated in Java")
|
*/
|
||||||
override fun onBackPressed() {
|
private fun addBackKeyListener() {
|
||||||
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
val count = list.count { !it.isOriginalData }
|
val count = list.count { !it.isOriginalData }
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
//说明有新增或者设置重量
|
|
||||||
saveDataRemindDialog()
|
saveDataRemindDialog()
|
||||||
return
|
return@addCallback
|
||||||
|
}
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
// if (list.size > firstReqSize) {
|
|
||||||
// //说明有新增的食材
|
|
||||||
// saveDataRemindDialog()
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// val filterResult = list.firstOrNull { (it.useWeight ?: 0.toDouble()) > 0.toDouble() }
|
|
||||||
// if (filterResult != null) {
|
|
||||||
// //说明有称重的数据
|
|
||||||
// saveDataRemindDialog()
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未保存数据提醒
|
||||||
|
*/
|
||||||
private fun saveDataRemindDialog() {
|
private fun saveDataRemindDialog() {
|
||||||
val remindBinding = LayoutFoodRemindBinding.inflate(layoutInflater)
|
val remindBinding = LayoutFoodRemindBinding.inflate(layoutInflater)
|
||||||
remindBinding.tvDialogTitle.text = "温馨提示"
|
remindBinding.tvDialogTitle.text = "温馨提示"
|
||||||
@@ -434,6 +447,9 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拍照成功回调
|
||||||
|
*/
|
||||||
private val cameraSuccessCallback: (Uri) -> Unit = { uri ->
|
private val cameraSuccessCallback: (Uri) -> Unit = { uri ->
|
||||||
Log.d(TAG, "takePhoto success")
|
Log.d(TAG, "takePhoto success")
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
@@ -457,11 +473,19 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拍照失败回调
|
||||||
|
*/
|
||||||
private val cameraFailureCallback: (String) -> Unit = { errMsg ->
|
private val cameraFailureCallback: (String) -> Unit = { errMsg ->
|
||||||
Log.d(TAG, "takePhoto failure")
|
Log.d(TAG, "takePhoto failure")
|
||||||
isTakingPhoto.set(false)
|
isTakingPhoto.set(false)
|
||||||
|
toast(errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用接口查询识别到的菜品
|
||||||
|
* @param list 食材列表
|
||||||
|
*/
|
||||||
private fun queryFood(list: List<FoodModule.IdNameScore>) {
|
private fun queryFood(list: List<FoodModule.IdNameScore>) {
|
||||||
Log.d(TAG, "takePhoto queryFood, list=${list.toString()}")
|
Log.d(TAG, "takePhoto queryFood, list=${list.toString()}")
|
||||||
//调用接口成功,返回食材列表设置isTakingPhoto.set(false),暂时写死数据
|
//调用接口成功,返回食材列表设置isTakingPhoto.set(false),暂时写死数据
|
||||||
@@ -477,6 +501,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
recognizeDialog.loadData(foodList)
|
recognizeDialog.loadData(foodList)
|
||||||
isTakingPhoto.set(false)
|
isTakingPhoto.set(false)
|
||||||
|
lastWeight = currentWeight
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@@ -47,6 +48,7 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
addViewListener()
|
addViewListener()
|
||||||
requestData(true)
|
requestData(true)
|
||||||
|
onBackPressedDispatcher.addCallback(this) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -95,14 +97,6 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
refreshPage(isCooking)
|
refreshPage(isCooking)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
@SuppressLint("GestureBackNavigation", "MissingSuperCall")
|
|
||||||
override fun onBackPressed() {
|
|
||||||
//super.onBackPressed()
|
|
||||||
//当前页面不允许返回
|
|
||||||
//dialog = toast("不允许返回操作")
|
|
||||||
}
|
|
||||||
|
|
||||||
private var list: MutableList<FoodRecord> = mutableListOf()
|
private var list: MutableList<FoodRecord> = mutableListOf()
|
||||||
private val dishAdapter by lazy {
|
private val dishAdapter by lazy {
|
||||||
SamplingAdapter(list = list).apply {
|
SamplingAdapter(list = list).apply {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package com.shuwei.dish.match.ui
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
@@ -13,8 +12,6 @@ import com.shuwei.dish.match.db.AppRepository
|
|||||||
import com.shuwei.dish.match.dialog.DialogTool
|
import com.shuwei.dish.match.dialog.DialogTool
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.entity.FoodRecord
|
||||||
import com.shuwei.dish.match.entity.FoodRecordBean
|
|
||||||
import com.shuwei.dish.match.net.NetViewModel
|
|
||||||
import com.shuwei.dish.match.ui.fragment.DishListFragment
|
import com.shuwei.dish.match.ui.fragment.DishListFragment
|
||||||
import com.shuwei.dish.match.utils.KeyboardUtil
|
import com.shuwei.dish.match.utils.KeyboardUtil
|
||||||
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
||||||
@@ -24,7 +21,6 @@ import com.shuwei.dish.match.utils.ext.toast
|
|||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
||||||
import kotlin.getValue
|
|
||||||
|
|
||||||
class SelectDishActivity : BaseActivity() {
|
class SelectDishActivity : BaseActivity() {
|
||||||
|
|
||||||
@@ -67,6 +63,7 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
initViewModel()
|
initViewModel()
|
||||||
addViewListener()
|
addViewListener()
|
||||||
loadFragment()
|
loadFragment()
|
||||||
|
onBackPressedDispatcher.addCallback(this) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initViewModel() {
|
private fun initViewModel() {
|
||||||
@@ -186,14 +183,6 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
@SuppressLint("GestureBackNavigation", "MissingSuperCall")
|
|
||||||
override fun onBackPressed() {
|
|
||||||
//super.onBackPressed()
|
|
||||||
//当前页面不允许返回
|
|
||||||
// dialog = toast("不允许返回操作")
|
|
||||||
}
|
|
||||||
|
|
||||||
private var isVisible = false
|
private var isVisible = false
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.addCallback
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.base.GlobalData
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
import com.shuwei.dish.match.databinding.ActivitySlaveBinding
|
import com.shuwei.dish.match.databinding.ActivitySlaveBinding
|
||||||
@@ -55,11 +55,9 @@ class SlaveActivity : BaseActivity() {
|
|||||||
* 禁用返回键,防止退回 InitActivity 后重复打开本页
|
* 禁用返回键,防止退回 InitActivity 后重复打开本页
|
||||||
*/
|
*/
|
||||||
private fun addBackKeyListener() {
|
private fun addBackKeyListener() {
|
||||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
onBackPressedDispatcher.addCallback(this) {
|
||||||
override fun handleOnBackPressed() {
|
|
||||||
// 禁用返回键,不执行任何操作
|
// 禁用返回键,不执行任何操作
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -242,10 +242,11 @@ class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
|||||||
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
|
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
|
||||||
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
||||||
SeasoningSearchDialog(
|
SeasoningSearchDialog(
|
||||||
|
activity = requireActivity() as BaseActivity,
|
||||||
weighIndex = sort,
|
weighIndex = sort,
|
||||||
weighAddress = currentAddress,
|
weighAddress = currentAddress,
|
||||||
clickName = entity.goodsName
|
clickName = entity.goodsName
|
||||||
).show(requireActivity() as BaseActivity) { item ->
|
) { item ->
|
||||||
syncItem(entity, item)
|
syncItem(entity, item)
|
||||||
// 3-调料
|
// 3-调料
|
||||||
entity.materialType = 3
|
entity.materialType = 3
|
||||||
@@ -256,7 +257,7 @@ class DeviceConfigFragment : BaseFragment<FragmentDeviceConfigBinding>() {
|
|||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
TextCellAdapter.loadLayout(frameLayout, entity)
|
||||||
}
|
}
|
||||||
}
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,16 +6,22 @@ import androidx.camera.core.CameraSelector
|
|||||||
import androidx.camera.view.CameraController
|
import androidx.camera.view.CameraController
|
||||||
import androidx.camera.view.LifecycleCameraController
|
import androidx.camera.view.LifecycleCameraController
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
class CameraUtils(private var activity: ComponentActivity) {
|
class CameraUtils(private var activity: ComponentActivity) {
|
||||||
|
|
||||||
private var cameraController: LifecycleCameraController? = null
|
private var cameraController: LifecycleCameraController? = null
|
||||||
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
private var photoCaptureHelper: PhotoCaptureHelper? = null
|
||||||
private var failCallback: ((msg: String) -> Unit)? = null
|
private var failCallback: ((msg: String) -> Unit)? = null
|
||||||
|
private var isCameraReady = false
|
||||||
|
|
||||||
// private var isCameraReady = false
|
|
||||||
fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = { }) {
|
fun takePhoto(succCallback: (Uri) -> Unit, failCallback: (msg: String) -> Unit = { }) {
|
||||||
this.failCallback = failCallback
|
this.failCallback = failCallback
|
||||||
|
// 相机未就绪时静默返回,避免触发错误提示
|
||||||
|
if (!isCameraReady) {
|
||||||
|
failCallback("")
|
||||||
|
return
|
||||||
|
}
|
||||||
cameraController?.let {
|
cameraController?.let {
|
||||||
if (photoCaptureHelper == null) {
|
if (photoCaptureHelper == null) {
|
||||||
initCaptureHelper()
|
initCaptureHelper()
|
||||||
@@ -74,10 +80,16 @@ class CameraUtils(private var activity: ComponentActivity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun bind() {
|
fun bind() {
|
||||||
|
isCameraReady = false
|
||||||
cameraController?.bindToLifecycle(activity)
|
cameraController?.bindToLifecycle(activity)
|
||||||
|
// 监听相机初始化完成,就绪后才允许拍照
|
||||||
|
cameraController?.initializationFuture?.addListener({
|
||||||
|
isCameraReady = true
|
||||||
|
}, ContextCompat.getMainExecutor(activity))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unbind() {
|
fun unbind() {
|
||||||
|
isCameraReady = false
|
||||||
cameraController?.unbind()
|
cameraController?.unbind()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 秤格子背景:白色底 + 灰色描边 + 圆角,与页面蓝色背景形成对比 -->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#FFFFFF" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/gray_d6" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
</shape>
|
||||||
@@ -56,7 +56,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"
|
||||||
android:padding="16dp"
|
android:padding="0dp"
|
||||||
tools:listitem="@layout/list_item_scale_data"/>
|
tools:listitem="@layout/list_item_scale_data"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user