feat(activity): 新增已采集食材列表页,支持搜索、删除及空视图展示
This commit is contained in:
@@ -115,6 +115,11 @@
|
|||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
|
<activity
|
||||||
|
android:name="com.shuwei.dish.match.ui.CollectedFoodActivity"
|
||||||
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name="com.shuwei.dish.match.ui.SlaveActivity"
|
android:name="com.shuwei.dish.match.ui.SlaveActivity"
|
||||||
android:theme="@style/Theme.DishMatch.NoSplash"
|
android:theme="@style/Theme.DishMatch.NoSplash"
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.shuwei.dish.match.databinding.ListItemCollectedFoodBinding
|
||||||
|
import com.shuwei.dish.match.entity.CollectedFoodItem
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表适配器
|
||||||
|
* 展示食材名称和已采集数量,支持删除操作
|
||||||
|
*/
|
||||||
|
class CollectedFoodAdapter(list: MutableList<CollectedFoodItem>) :
|
||||||
|
BaseQuickAdapter<CollectedFoodItem, CollectedFoodAdapter.VH>(list) {
|
||||||
|
|
||||||
|
/** ViewHolder,持有列表项 ViewBinding */
|
||||||
|
inner class VH(val binding: ListItemCollectedFoodBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
|
val binding = ListItemCollectedFoodBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: VH, position: Int, item: CollectedFoodItem?) {
|
||||||
|
item ?: return
|
||||||
|
holder.binding.tvFoodName.text = item.foodName.split("WP").first()
|
||||||
|
holder.binding.tvCollectCount.text = "已采集${item.collectCount}"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,8 +40,6 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityBaseBinding
|
private lateinit var binding: ActivityBaseBinding
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
// 提前隐藏系统栏,避免窗口创建时导航栏闪烁
|
// 提前隐藏系统栏,避免窗口创建时导航栏闪烁
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package com.shuwei.dish.match.db
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.shuwei.dish.match.entity.CollectedFoodItem
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.objbox.ObjectBox
|
||||||
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
|
||||||
import com.shuwei.dish.match.entity.SeasoningSlotEntity
|
import com.shuwei.dish.match.entity.SeasoningSlotEntity
|
||||||
@@ -248,4 +250,39 @@ class DbViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表 UI 状态流
|
||||||
|
* 元素为按名称分组后的(名称,数量)数据
|
||||||
|
*/
|
||||||
|
private val _collectedFoodListState = MutableStateFlow<List<CollectedFoodItem>>(emptyList())
|
||||||
|
val collectedFoodListState: StateFlow<List<CollectedFoodItem>> = _collectedFoodListState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载已采集食材列表,按名称分组统计数量
|
||||||
|
* 使用属性查询只读 name 字段,不加载 foodVector,节省内存
|
||||||
|
* @param nameFilter 名称过滤关键词,为空时加载全部
|
||||||
|
*/
|
||||||
|
fun loadCollectedFoodList(nameFilter: String? = null) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val result = ObjectBox.queryFoodNameCounts(nameFilter)
|
||||||
|
_collectedFoodListState.value = result.map { (name, count) ->
|
||||||
|
CollectedFoodItem(foodName = name, collectCount = count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定名称的所有采集记录,删除完成后刷新列表
|
||||||
|
* @param foodName 食材名称
|
||||||
|
* @param nameFilter 当前搜索关键词,用于删除后刷新列表
|
||||||
|
*/
|
||||||
|
fun removeCollectedFood(foodName: String, nameFilter: String? = null) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
ObjectBox.remove(foodName)
|
||||||
|
loadCollectedFoodList(nameFilter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ open class CommonDialog(
|
|||||||
private lateinit var binding: DialogCommonBinding
|
private lateinit var binding: DialogCommonBinding
|
||||||
|
|
||||||
private var titleText: String? = null
|
private var titleText: String? = null
|
||||||
private var contentText: String? = null
|
private var contentText: CharSequence? = null
|
||||||
private var negativeText = "取消"
|
private var negativeText = "取消"
|
||||||
private var positiveText = "确认"
|
private var positiveText = "确认"
|
||||||
private var neutralText: String? = null
|
private var neutralText: String? = null
|
||||||
@@ -36,7 +36,7 @@ open class CommonDialog(
|
|||||||
fun setTitle(text: String): CommonDialog = apply { titleText = text }
|
fun setTitle(text: String): CommonDialog = apply { titleText = text }
|
||||||
|
|
||||||
/** 设置内容,为空时隐藏 */
|
/** 设置内容,为空时隐藏 */
|
||||||
fun setContent(text: String): CommonDialog = apply { contentText = text }
|
fun setContent(text: CharSequence): CommonDialog = apply { contentText = text }
|
||||||
|
|
||||||
/** 设置左侧取消按钮文字及点击回调(3按钮模式下对应顶部按钮) */
|
/** 设置左侧取消按钮文字及点击回调(3按钮模式下对应顶部按钮) */
|
||||||
fun setNegativeButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
fun setNegativeButton(text: String, onClick: (() -> Unit)? = null): CommonDialog = apply {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class FoodSearchDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
||||||
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) }
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) }
|
||||||
|
|
||||||
initObserver()
|
initObserver()
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ class FoodSearchDialog(
|
|||||||
}
|
}
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import com.shuwei.dish.match.utils.ext.buildSpannableString
|
|||||||
import com.shuwei.dish.match.utils.ext.dp
|
import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +132,7 @@ class SeasoningSearchDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
||||||
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) }
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) }
|
||||||
|
|
||||||
// 去皮按钮
|
// 去皮按钮
|
||||||
binding.tvClear.setOnClickListener {
|
binding.tvClear.setOnClickListener {
|
||||||
@@ -193,7 +192,7 @@ class SeasoningSearchDialog(
|
|||||||
}
|
}
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class SeasoningSelectDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
binding.ivSearch.setOnClickListener { searchGoods(it) }
|
||||||
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) }
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 弹窗显示时自动加载默认调料列表 */
|
/** 弹窗显示时自动加载默认调料列表 */
|
||||||
@@ -126,7 +126,7 @@ class SeasoningSelectDialog(
|
|||||||
}
|
}
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getGoodsList()
|
getGoodsList()
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard( v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.shuwei.dish.match.entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表项数据模型
|
||||||
|
* @param foodName 食材名称
|
||||||
|
* @param collectCount 已采集数量
|
||||||
|
*/
|
||||||
|
data class CollectedFoodItem(
|
||||||
|
val foodName: String = "",
|
||||||
|
val collectCount: Int = 0
|
||||||
|
)
|
||||||
@@ -213,6 +213,31 @@ object ObjectBox {
|
|||||||
getBox<Food>()?.query(Food_.name.equal(name))?.build()?.remove()
|
getBox<Food>()?.query(Food_.name.equal(name))?.build()?.remove()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按名称分组统计采集数量
|
||||||
|
* 使用属性查询只加载 name 字段,不加载 foodVector,节省大量内存
|
||||||
|
* @param nameFilter 名称过滤关键词,为空时查询全部
|
||||||
|
* @return 按名称分组后的 (名称, 数量) 列表,按名称排序
|
||||||
|
*/
|
||||||
|
suspend fun queryFoodNameCounts(nameFilter: String? = null) = safeDbOp {
|
||||||
|
val box = getBox<Food>() ?: return@safeDbOp emptyList<Pair<String, Int>>()
|
||||||
|
val query = if (!nameFilter.isNullOrBlank()) {
|
||||||
|
box.query(Food_.name.contains(nameFilter)).build()
|
||||||
|
} else {
|
||||||
|
box.query().build()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 只查 name 字段,完全不加载 foodVector
|
||||||
|
query.property(Food_.name).findStrings()
|
||||||
|
.groupingBy { it }
|
||||||
|
.eachCount()
|
||||||
|
.map { (name, count) -> Pair(name, count) }
|
||||||
|
.sortedBy { it.first }
|
||||||
|
} finally {
|
||||||
|
query.close()
|
||||||
|
}
|
||||||
|
} ?: emptyList()
|
||||||
|
|
||||||
private val dbMutex = Mutex() // 协程并发锁,保证写入操作原子性
|
private val dbMutex = Mutex() // 协程并发锁,保证写入操作原子性
|
||||||
private const val DB_DIR_NAME = "objectbox" // ObjectBox 默认数据库目录
|
private const val DB_DIR_NAME = "objectbox" // ObjectBox 默认数据库目录
|
||||||
private const val BACKUP_DIR_NAME = "objectbox_backup" // 备份目录
|
private const val BACKUP_DIR_NAME = "objectbox_backup" // 备份目录
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
|
import android.text.style.StyleSpan
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.adapter.CollectedFoodAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.databinding.ActivityCollectedFoodBinding
|
||||||
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
|
import com.shuwei.dish.match.entity.CollectedFoodItem
|
||||||
|
import com.shuwei.dish.match.utils.KeyboardUtil
|
||||||
|
import com.shuwei.dish.match.utils.ext.appendText
|
||||||
|
import com.shuwei.dish.match.utils.ext.buildSpannableString
|
||||||
|
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 kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表页面
|
||||||
|
* 展示所有已采集的食材及其采集数量,支持搜索和删除
|
||||||
|
*/
|
||||||
|
class CollectedFoodActivity : BaseActivity() {
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityCollectedFoodBinding
|
||||||
|
|
||||||
|
private val foodList = mutableListOf<CollectedFoodItem>()
|
||||||
|
|
||||||
|
private var emptyViewBinding: LayoutEmptyViewBinding? = null
|
||||||
|
|
||||||
|
private val adapter by lazy {
|
||||||
|
CollectedFoodAdapter(foodList).apply {
|
||||||
|
isStateViewEnable = true
|
||||||
|
// 点击删除按钮,移除对应食材
|
||||||
|
addOnItemChildClickListener(R.id.ivDelete) { _, _, position ->
|
||||||
|
showDeleteDialog(foodList[position].foodName)
|
||||||
|
}
|
||||||
|
setOnItemClickListener { _, view, _ ->
|
||||||
|
KeyboardUtil.hideKeyboard(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除弹窗
|
||||||
|
*/
|
||||||
|
private fun showDeleteDialog(foodName: String) {
|
||||||
|
val showFoodName = foodName.split("WP").first()
|
||||||
|
val separator = if (showFoodName.length <= 10) "\n" else ""
|
||||||
|
val content = buildSpannableString {
|
||||||
|
appendText("食材:")
|
||||||
|
appendText(showFoodName, StyleSpan(Typeface.BOLD), ForegroundColorSpan(Color.BLACK))
|
||||||
|
appendText(" 删除后无法恢复,${separator}确认要删除吗?")
|
||||||
|
}
|
||||||
|
CommonDialog(this)
|
||||||
|
.setTitle("温馨提示")
|
||||||
|
.setContent(content)
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("确认") {
|
||||||
|
appViewModel.removeCollectedFood(
|
||||||
|
foodName = foodName,
|
||||||
|
nameFilter = binding.editSearch.text.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
statusBarDarkFont(enable = true)
|
||||||
|
binding = ActivityCollectedFoodBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
setHeaderBackground()
|
||||||
|
binding.root.setOnClickListener { v ->
|
||||||
|
KeyboardUtil.hideKeyboard(v)
|
||||||
|
}
|
||||||
|
setTitleBar(titleBarAction = {
|
||||||
|
it.visible()
|
||||||
|
it.setOnClickListener { v ->
|
||||||
|
KeyboardUtil.hideKeyboard(v)
|
||||||
|
}
|
||||||
|
}, titleAction = {
|
||||||
|
it.text = "已采集食材"
|
||||||
|
}, rightIconActon = {
|
||||||
|
it.gone()
|
||||||
|
}, backAction = {
|
||||||
|
it.visible()
|
||||||
|
it.setOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
initRecyclerView()
|
||||||
|
initSearch()
|
||||||
|
initObserver()
|
||||||
|
loadCollectedFoodList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadCollectedFoodList(name: String = "") {
|
||||||
|
appViewModel.loadCollectedFoodList(nameFilter = name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收集 searchFoodState,统一处理 Loading / Success / Error 状态
|
||||||
|
*/
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun initObserver() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
appViewModel.collectedFoodListState.collect { items ->
|
||||||
|
foodList.clear()
|
||||||
|
foodList.addAll(items)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
loadEmptyView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 展示空视图 */
|
||||||
|
private fun loadEmptyView() {
|
||||||
|
if (emptyViewBinding == null) {
|
||||||
|
emptyViewBinding = LayoutEmptyViewBinding.inflate(
|
||||||
|
LayoutInflater.from(this), binding.rvCollectedFood, false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
emptyViewBinding!!.tvContent.text = "暂无数据"
|
||||||
|
emptyViewBinding!!.tvSubContent.text = "未查询到食材信息"
|
||||||
|
adapter.stateView = emptyViewBinding!!.root
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化列表 */
|
||||||
|
private fun initRecyclerView() {
|
||||||
|
binding.rvCollectedFood.run {
|
||||||
|
layoutManager = LinearLayoutManager(this@CollectedFoodActivity)
|
||||||
|
adapter = this@CollectedFoodActivity.adapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化搜索栏交互 */
|
||||||
|
private fun initSearch() {
|
||||||
|
binding.btnSearch.setOnClickListener { v ->
|
||||||
|
performSearch {
|
||||||
|
toast(binding.editSearch.hint.toString())
|
||||||
|
}
|
||||||
|
KeyboardUtil.hideKeyboard(v)
|
||||||
|
}
|
||||||
|
binding.editSearch.run {
|
||||||
|
addTextChangedListener {
|
||||||
|
performSearch {
|
||||||
|
loadCollectedFoodList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setOnEditorActionListener { v, actionId, _ ->
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||||
|
performSearch {
|
||||||
|
toast(binding.editSearch.hint.toString())
|
||||||
|
}
|
||||||
|
KeyboardUtil.hideKeyboard(v)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据关键词过滤食材列表 */
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun performSearch(action: () -> Unit) {
|
||||||
|
val keyword = binding.editSearch.text.toString().trim()
|
||||||
|
if (keyword.isEmpty()) {
|
||||||
|
action()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 根据关键词从数据库查询并刷新列表
|
||||||
|
loadCollectedFoodList(keyword)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -256,7 +256,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
setSelection(text.length)
|
setSelection(text.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchDishType() {
|
private fun searchDishType() {
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class FoodSearchActivity : BaseActivity() {
|
|||||||
binding.ivDishSearch.setOnClickListener { v ->
|
binding.ivDishSearch.setOnClickListener { v ->
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getInputAndSearch()
|
getInputAndSearch()
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
binding.refreshLayout.setEnableRefresh(true)
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
binding.refreshLayout.setEnableLoadMore(false)
|
binding.refreshLayout.setEnableLoadMore(false)
|
||||||
@@ -136,13 +136,13 @@ class FoodSearchActivity : BaseActivity() {
|
|||||||
queryListInfo(foodName!!)
|
queryListInfo(foodName!!)
|
||||||
}
|
}
|
||||||
binding.root.setOnClickListener { v ->
|
binding.root.setOnClickListener { v ->
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
binding.etInputDish.let { v ->
|
binding.etInputDish.let { v ->
|
||||||
v.addOnActionSearchListener {
|
v.addOnActionSearchListener {
|
||||||
pageNo = 1
|
pageNo = 1
|
||||||
getInputAndSearch()
|
getInputAndSearch()
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard( v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
setSelection(text.length)
|
setSelection(text.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyboardUtil.hideKeyboard(v.context, v)
|
KeyboardUtil.hideKeyboard(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
putExtra(FoodSearchActivity.DINNER_TYPE, dinnerType)
|
putExtra(FoodSearchActivity.DINNER_TYPE, dinnerType)
|
||||||
putExtra(FoodSearchActivity.FOOD_NAME, searchText)
|
putExtra(FoodSearchActivity.FOOD_NAME, searchText)
|
||||||
}
|
}
|
||||||
KeyboardUtil.hideKeyboard(this, binding.etInputDish)
|
KeyboardUtil.hideKeyboard(binding.etInputDish)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFragment() {
|
private fun loadFragment() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.shuwei.dish.match.ui.fragment
|
package com.shuwei.dish.match.ui.fragment
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@@ -22,6 +23,7 @@ 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.CollectedFoodActivity
|
||||||
import com.shuwei.dish.match.ui.SingleFragmentActivity
|
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.CameraUtils
|
||||||
@@ -243,7 +245,7 @@ class CollectFragment : BaseFragment<FragmentCollectBinding>(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.btnCollectedFood.setOnClickListener {
|
binding.btnCollectedFood.setOnClickListener {
|
||||||
// startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java))
|
startActivity(Intent(requireActivity(), CollectedFoodActivity::class.java))
|
||||||
}
|
}
|
||||||
binding.btnTakePhoto.clickWithDebounce {
|
binding.btnTakePhoto.clickWithDebounce {
|
||||||
val count = foodCollectionList.count { it.bitmap != null }
|
val count = foodCollectionList.count { it.bitmap != null }
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
|
|
||||||
object KeyboardUtil {
|
object KeyboardUtil {
|
||||||
|
|
||||||
fun hideKeyboard(context: Context, view: View) {
|
fun hideKeyboard(view: View) {
|
||||||
|
val context = view.context
|
||||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
imm.hideSoftInputFromWindow(view.windowToken, 0)
|
imm.hideSoftInputFromWindow(view.windowToken, 0)
|
||||||
view.clearFocus() // 清除焦点避免键盘再次弹出
|
view.clearFocus() // 清除焦点避免键盘再次弹出
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- 红色圆形背景 + 白色 X 图标,用于列表项删除按钮 -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportWidth="48"
|
||||||
|
android:viewportHeight="48">
|
||||||
|
|
||||||
|
<!-- 红色圆形背景 #FFEE4444 -->
|
||||||
|
<path
|
||||||
|
android:fillColor="#00BC71"
|
||||||
|
android:pathData="M24,2C11.85,2 2,11.85 2,24C2,36.15 11.85,46 24,46C36.15,46 46,36.15 46,24C46,11.85 36.15,2 24,2Z" />
|
||||||
|
|
||||||
|
<!-- 白色 X 图标 -->
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M33,16.41L31.59,15L24,22.59L16.41,15L15,16.41L22.59,24L15,31.59L16.41,33L24,25.41L31.59,33L33,31.59L25.41,24L33,16.41Z" />
|
||||||
|
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:background="@color/white"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/editSearch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/setting_border_gray3"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:hint="输入食材名称"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="47dp"
|
||||||
|
android:paddingEnd="80dp"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textColorHint="#FFC4CFDA"
|
||||||
|
android:textSize="36sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btnSearch"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/ic_search2"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- 已采集食材列表 -->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvCollectedFood"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
tools:itemCount="5"
|
||||||
|
tools:listitem="@layout/list_item_collected_food" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
android:layout_marginStart="32dp"
|
android:layout_marginStart="32dp"
|
||||||
android:layout_marginTop="30dp"
|
android:layout_marginTop="30dp"
|
||||||
android:drawablePadding="17dp"
|
android:drawablePadding="17dp"
|
||||||
android:text="餐品采集"
|
android:text="食材采集"
|
||||||
android:textColor="@color/black"
|
android:textColor="@color/black"
|
||||||
android:textSize="36sp"
|
android:textSize="36sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
android:layout_marginEnd="32dp"
|
android:layout_marginEnd="32dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:includeFontPadding="false"
|
android:includeFontPadding="false"
|
||||||
android:text="已采集餐品"
|
android:text="已采集食材"
|
||||||
android:textColor="#ff5e7585"
|
android:textColor="#ff5e7585"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingHorizontal="32dp"
|
||||||
|
android:paddingVertical="24dp">
|
||||||
|
|
||||||
|
<!-- 食材名称和采集数量 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFoodName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="三河小炒" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvCollectCount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textColor="#ff5e7585"
|
||||||
|
android:textSize="26sp"
|
||||||
|
tools:text="已采集153" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 删除按钮 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivDelete"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:padding="25dp"
|
||||||
|
android:src="@drawable/ic_close_red"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginHorizontal="32dp"
|
||||||
|
android:background="#FFE8EDF2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user