From 768bde79a1a99674431a137f2147889d51a7586a Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Fri, 17 Apr 2026 15:43:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(fragment):=20=E6=96=B0=E5=A2=9E=E8=B0=83?= =?UTF-8?q?=E6=96=99=E9=80=89=E6=8B=A9=E5=BC=B9=E7=AA=97=E5=B9=B6=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E6=A0=BC=E5=AD=90=E7=82=B9=E5=87=BB=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../match/adapter/Seasoning18GridAdapter.kt | 10 + .../match/adapter/Seasoning22GridAdapter.kt | 10 + .../match/dialog/SeasoningSelectDialog.kt | 191 ++++++++++++++++++ .../ui/fragment/SeasoningConfigFragment.kt | 24 +++ .../res/layout/dialog_seasoning_select.xml | 89 ++++++++ 5 files changed, 324 insertions(+) create mode 100644 app/src/main/java/com/shuwei/dish/match/dialog/SeasoningSelectDialog.kt create mode 100644 app/src/main/res/layout/dialog_seasoning_select.xml diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt index 6d4201b..2b4bf8d 100644 --- a/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt +++ b/app/src/main/java/com/shuwei/dish/match/adapter/Seasoning18GridAdapter.kt @@ -59,6 +59,16 @@ class Seasoning18GridAdapter : BaseQuickAdapter Unit +) : BottomSheetDialog(activity, R.style.BottomSheet) { + + companion object { + const val TAG = "SeasoningSelectDialog" + } + + private val binding = DialogSeasoningSelectBinding.inflate(LayoutInflater.from(activity)) + private val list = mutableListOf() + private val adapter = SeasoningSearchAdapter(list).apply { + setOnItemClickListener { _, _, position -> + list[position].isClicked = true + notifyItemChanged(position) + Handler(Looper.getMainLooper()).postDelayed({ + onItemSelected(list[position]) + dismiss() + }, 300) + } + } + + private var goodsName: String? = null + private var pageNo = 1 + private val pageSize = 50 + + 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 { + 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@SeasoningSelectDialog.adapter + addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(rv, dx, dy) + // 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突 + val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top + binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0) + } + }) + } + + binding.refreshLayout.run { + setEnableRefresh(false) + setEnableLoadMore(false) + setOnRefreshListener { pageNo = 1; getGoodsList() } + setOnLoadMoreListener { getGoodsList() } + } + + binding.ivSearch.setOnClickListener { searchGoods(it) } + binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it.context, it) } + } + + /** 弹窗显示时自动加载默认调料列表 */ + override fun show() { + super.show() + pageNo = 1 + getGoodsList() + } + + /** + * 触发搜索:校验输入、隐藏键盘、发起请求 + */ + private fun searchGoods(v: View) { + if (goodsName.isNullOrBlank()) { + activity.toast("请${binding.etSheetInput.hint}") + return + } + pageNo = 1 + getGoodsList() + KeyboardUtil.hideKeyboard(v.context, v) + } + + /** + * 请求调料列表(临时使用本地模拟数据,正式联调时替换为真实接口) + */ + private fun getGoodsList() { + // TODO: 联调时注释掉下方模拟数据,取消注释真实接口调用 + val mockData = mutableListOf( + SeasoningEntity(goodsId = "1", goodsName = "精盐"), + SeasoningEntity(goodsId = "2", goodsName = "鸡精"), + SeasoningEntity(goodsId = "3", goodsName = "陈醋"), + SeasoningEntity(goodsId = "4", goodsName = "老抽"), + SeasoningEntity(goodsId = "5", goodsName = "生抽"), + SeasoningEntity(goodsId = "6", goodsName = "花生油"), + SeasoningEntity(goodsId = "7", goodsName = "菜籽油"), + SeasoningEntity(goodsId = "8", goodsName = "胡椒粉"), + SeasoningEntity(goodsId = "9", goodsName = "十三香"), + SeasoningEntity(goodsId = "10", goodsName = "料酒"), + SeasoningEntity(goodsId = "11", goodsName = "白醋") + ) + loadGoodsList(mockData) + +// val param = mutableMapOf( +// "goodsType" to "1", +// "placeId" to BaseApp.canteenId, +// "pageNum" to pageNo, +// "pageSize" to pageSize +// ) +// if (!goodsName.isNullOrBlank()) { +// param["goodsName"] = goodsName!! +// } +// activity.querySeasoningList(param = param, onSuccess = { +// loadGoodsList(it) +// }, onFailure = { _, msg -> +// activity.toast(msg) +// finishRefresh() +// }) + } + + /** + * 将返回数据填充到列表 + */ + @SuppressLint("NotifyDataSetChanged") + private fun loadGoodsList(records: MutableList?) { + finishRefresh() + if (records.isNullOrEmpty()) { + activity.toast("暂未搜索到调料信息") + return + } + if (pageNo == 1) list.clear() + list.addAll(records) + adapter.notifyDataSetChanged() + val isLoadMoreEnable = records.size >= pageSize + binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable) + if (isLoadMoreEnable) pageNo++ + } + + private fun finishRefresh() { + if (pageNo == 1) binding.refreshLayout.finishRefresh() + else binding.refreshLayout.finishLoadMore() + } +} diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt index 2e35dbf..e87d8dd 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/SeasoningConfigFragment.kt @@ -11,6 +11,7 @@ import com.shuwei.dish.match.adapter.Seasoning18GridAdapter import com.shuwei.dish.match.adapter.Seasoning22GridAdapter import com.shuwei.dish.match.base.BaseFragment import com.shuwei.dish.match.databinding.FragmentSeasoningConfigBinding +import com.shuwei.dish.match.dialog.SeasoningSelectDialog import com.shuwei.dish.match.ui.SettingActivity import com.shuwei.dish.match.utils.ext.dp @@ -31,9 +32,32 @@ class SeasoningConfigFragment : BaseFragment() { settingActivity = activity as SettingActivity // initViewModel() setupRecyclerViews() + bindAdapterClicks() loadData() } + /** 绑定两个 Adapter 的格子点击,弹出调料选择弹窗 */ + private fun bindAdapterClicks() { + adapter22.onItemClick = { _, position -> + SeasoningSelectDialog( + activity = settingActivity, + clickIndex = position, + onItemSelected = { item -> + adapter22.updateItemName(position, item.goodsName ?: "") + } + ).show() + } + adapter18.onItemClick = { _, position -> + SeasoningSelectDialog( + activity = settingActivity, + clickIndex = position, + onItemSelected = { item -> + adapter18.updateItemName(position, item.goodsName ?: "") + } + ).show() + } + } + // /** 初始化 ViewModel */ // private fun initViewModel() { // val factory = AppFactory(AppRepository(BaseApp.instance!!.database.appDao())) diff --git a/app/src/main/res/layout/dialog_seasoning_select.xml b/app/src/main/res/layout/dialog_seasoning_select.xml new file mode 100644 index 0000000..11b6669 --- /dev/null +++ b/app/src/main/res/layout/dialog_seasoning_select.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + +