Files
StallDualScreen/app/src/main/java/com/sw/dualscreen/view/CustomBottomSheetDialog.kt
T
2025-08-01 15:57:12 +08:00

138 lines
4.9 KiB
Kotlin

package com.sw.dualscreen.view
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.sw.dualscreen.R
import com.sw.dualscreen.adapter.GenericItemAdapter
import com.sw.dualscreen.adapter.GridSpacingItemDecoration
import com.sw.dualscreen.adapter.dpToPx
import com.sw.dualscreen.databinding.BottomSheetDialogBinding
import com.sw.dualscreen.databinding.ItemSearchFoodInfoBinding
import com.sw.dualscreen.model.response.FoodInfo
import com.sw.dualscreen.utils.Debouncer
import com.sw.dualscreen.viewmodel.UserViewModel
import kotlinx.coroutines.launch
import timber.log.Timber
class CustomBottomSheetDialog(
val viewModel: UserViewModel,
val itemClickCallback: (FoodInfo) -> Unit
) : BottomSheetDialogFragment() {
private lateinit var binding: BottomSheetDialogBinding
private lateinit var adapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
private var checkedItem: FoodInfo? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = BottomSheetDialogBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val debouncer = Debouncer(3000)
initView()
binding.ivSearch.setOnClickListener {
debouncer.debounce {
viewModel.searchByFoodName(binding.etSearch.text.toString())
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.BottomSheetDialogTheme)
setDialogStyle()
}
private fun setDialogStyle() {
dialog?.window?.let {
it.decorView.background = ColorDrawable(Color.TRANSPARENT)
it.decorView.setPadding(0, 0, 0, 0)
it.attributes?.apply {
width = ViewGroup.LayoutParams.MATCH_PARENT
height = ViewGroup.LayoutParams.MATCH_PARENT
}
it.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
}
companion object {
fun newInstance(
viewModel: UserViewModel,
itemClickCallback: (FoodInfo) -> Unit
): CustomBottomSheetDialog {
return CustomBottomSheetDialog(viewModel, itemClickCallback)
}
}
private fun initView() {
adapter = createAdapter()
binding.recyclerview.layoutManager = GridLayoutManager(context, 2)
// 添加间距装饰(12dp)
binding.recyclerview.addItemDecoration(
GridSpacingItemDecoration(
spanCount = 2,
spacing = requireContext().dpToPx(30),
includeEdge = false // 包含边缘间距
)
)
binding.recyclerview.adapter = adapter
registerDataChange()
}
private fun registerDataChange() {
lifecycleScope.launch {
viewModel.searchFoodInfoList.collect {
adapter.updateData(it)
}
}
}
private fun createAdapter(): GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding> {
return GenericItemAdapter(
items = emptyList(),
bindingInflater = ItemSearchFoodInfoBinding::inflate,
bindCallback = { item, position ->
this.tvName.text = item.foodName
if (item.id != checkedItem?.id) {
this.tvName.typeface = Typeface.defaultFromStyle(Typeface.NORMAL)
this.tvName.setTextColor(resources.getColor(R.color.search_normal))
this.llRoot.setBackgroundResource(R.drawable.grid_search_item_normal)
} else {
this.tvName.typeface = Typeface.defaultFromStyle(Typeface.BOLD)
this.tvName.setTextColor(resources.getColor(R.color.search_checked))
this.llRoot.setBackgroundResource(R.drawable.grid_search_item_checked)
}
this.llRoot.setOnClickListener {
Timber.d("itemClick ${item.foodName}, position = $position")
checkedItem = item
// viewModel.updateCurrentItem(item)
itemClickCallback(item)
adapter.notifyDataSetChanged()
}
}
)
}
override fun dismiss() {
viewModel.cleanSearchFoodInfoList()
super.dismiss()
}
}