首页、支付功能

This commit is contained in:
2025-11-26 18:57:53 +08:00
parent 60b712f216
commit 88179e27b7
64 changed files with 3380 additions and 319 deletions
@@ -1,5 +1,6 @@
package com.sw.dualscreen.view
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.Typeface
@@ -14,6 +15,7 @@ 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.SearchFoodAdapter
import com.sw.dualscreen.adapter.dpToPx
import com.sw.dualscreen.databinding.BottomSheetDialogBinding
import com.sw.dualscreen.databinding.ItemSearchFoodInfoBinding
@@ -27,12 +29,29 @@ import timber.log.Timber
/**
* 底部搜索结果弹窗
*/
@SuppressLint("NotifyDataSetChanged")
class CustomBottomSheetDialog(
val viewModel: UserViewModel,
val itemClickCallback: (FoodInfo) -> Unit
) : BottomSheetDialogFragment() {
private lateinit var binding: BottomSheetDialogBinding
private lateinit var adapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
// lateinit var adapter: GenericItemAdapter<FoodInfo, ItemSearchFoodInfoBinding>
private val searchFoodList = mutableListOf<FoodInfo>()
private val adapter by lazy {
SearchFoodAdapter(searchFoodList).apply {
setOnItemClickListener { adapter, view, position ->
searchFoodList.forEachIndexed { index, info ->
searchFoodList[index].isChecked = index == position
}
val item = searchFoodList[position]
Timber.d("itemClick ${item.foodName}, position = $position")
itemClickCallback(item)
checkedItem = item
notifyDataSetChanged()
dismissAllowingStateLoss()
}
}
}
private var checkedItem: FoodInfo? = null
private val debouncer = Debouncer(2000)
@@ -83,18 +102,21 @@ class CustomBottomSheetDialog(
}
private fun initView() {
binding.viewClose.setOnClickListener { dismiss() }
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
//binding.recyclerview.addItemDecoration(
// GridSpacingItemDecoration(
// spanCount = 2,
// spacing = requireContext().dpToPx(30),
// includeEdge = false // 包含边缘间距
// )
//)
//adapter = createAdapter()
//binding.recyclerview.adapter = adapter
binding.viewClose.setOnClickListener { dismiss() }
binding.recyclerview.let {
it.layoutManager = GridLayoutManager(context, 2)
it.adapter = adapter
}
binding.ivSearch.setOnClickListener {
searchInfo()
}
@@ -110,40 +132,43 @@ class CustomBottomSheetDialog(
}
}
@SuppressLint("NotifyDataSetChanged")
private fun registerDataChange() {
lifecycleScope.launch {
viewModel.searchFoodInfoList.collect {
adapter.updateData(it)
searchFoodList.clear()
searchFoodList.addAll(it)
adapter.notifyDataSetChanged()
}
}
}
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()
}
}
)
}
// 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 onCancel(dialog: DialogInterface) {
Timber.d("onCancel")
@@ -29,7 +29,8 @@ public class CustomImageView extends androidx.appcompat.widget.AppCompatImageVie
/**
* 最大高度
*/
private static final int MAX_HEIGHT = 280;
// private static final int MAX_HEIGHT = 280;
private static final int MAX_HEIGHT = 250;
private boolean isDrawText = false;
private Drawable bigRedDrawable;
@@ -100,6 +101,14 @@ public class CustomImageView extends androidx.appcompat.widget.AppCompatImageVie
}
}
public void setImageDrawable2(boolean isBig, Boolean isRed) {
if (isBig) {
setImageDrawable(isRed ? bigRedDrawable : bigGreenDrawable);
} else {
setImageDrawable(isRed ? redDrawable : greenDrawable);
}
}
public void setCustomHeightPercent(float percent, boolean isAnimation) {
Timber.d("setCustomHeightPercent percent = %s", percent);
if (percent<= 0){