feat(swipe): 接入 SwipeRevealLayout 并统一侧滑删除交互
引入 SwipeRevealLayout 替换原有滑动删除方案,修复点击冲突与开合状态问题,并在菜品列表与食材列表中统一删除确认与侧滑行为。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,11 +12,22 @@ import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
|||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import java.text.DecimalFormat
|
import com.shuwei.dish.match.view.swipereveallayout.ViewBinderHelper
|
||||||
|
|
||||||
class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
||||||
BaseQuickAdapter<CookFoodGoodsEntity, DishPartAdapter.VH>(list) {
|
BaseQuickAdapter<CookFoodGoodsEntity, DishPartAdapter.VH>(list) {
|
||||||
|
|
||||||
|
var onDeleteClick: ((position: Int) -> Unit)? = null
|
||||||
|
var onItemClick: ((position: Int) -> Unit)? = null
|
||||||
|
|
||||||
|
private val viewBinderHelper = ViewBinderHelper().apply {
|
||||||
|
setOpenOnlyOne(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeAll() {
|
||||||
|
viewBinderHelper.closeAll()
|
||||||
|
}
|
||||||
|
|
||||||
inner class VH(var binding: ListItemDishCookBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemDishCookBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
@@ -27,33 +38,47 @@ class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
|||||||
|
|
||||||
override fun onBindViewHolder(holder: VH, position: Int, item: CookFoodGoodsEntity?) {
|
override fun onBindViewHolder(holder: VH, position: Int, item: CookFoodGoodsEntity?) {
|
||||||
holder.binding.run {
|
holder.binding.run {
|
||||||
tvDishName.text = item!!.goodsName
|
val data = item ?: return
|
||||||
tvDishType.text = if (item.materialType == 1) "主辅材:主材" else if (item.materialType == 2) "主辅材:辅材" else ""
|
val itemId = data.goodsId ?: "${position}_${data.goodsName ?: ""}"
|
||||||
//"${DecimalFormat("#").format(item.useWeight)}克"
|
viewBinderHelper.bind(swipeRevealLayout, itemId)
|
||||||
|
// 暂时禁用侧滑能力,后续需要放开时改回 unlockSwipe + layoutDelete.visible()
|
||||||
|
viewBinderHelper.lockSwipe(itemId)
|
||||||
|
swipeRevealLayout.close(false)
|
||||||
|
layoutDelete.gone()
|
||||||
|
|
||||||
|
layoutDelete.setOnClickListener {
|
||||||
|
onDeleteClick?.invoke(holder.bindingAdapterPosition)
|
||||||
|
}
|
||||||
|
clBlock.setOnClickListener {
|
||||||
|
onItemClick?.invoke(holder.bindingAdapterPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
tvDishName.text = data.goodsName
|
||||||
|
tvDishType.text = if (data.materialType == 1) "主辅材:主材" else if (data.materialType == 2) "主辅材:辅材" else ""
|
||||||
tvDishWeight.text =
|
tvDishWeight.text =
|
||||||
if (item.useWeight == null || item.useWeight == 0.toDouble()) "" else "${item.useWeight!!.roundedOneDecimalPlace()}克"
|
if (data.useWeight == null || data.useWeight == 0.toDouble()) "" else "${data.useWeight!!.roundedOneDecimalPlace()}克"
|
||||||
tvDishWeight.setTextColor(
|
tvDishWeight.setTextColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
context,
|
context,
|
||||||
if (item.isSamplingPage) R.color.black999 else R.color.dish_green
|
if (data.isSamplingPage) R.color.black999 else R.color.dish_green
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
ivOperateIcon.run {
|
ivOperateIcon.run {
|
||||||
if (item.isSamplingPage) gone() else visible()
|
if (data.isSamplingPage) gone() else visible()
|
||||||
}
|
}
|
||||||
ivClearIcon.visible()
|
ivClearIcon.visible()
|
||||||
ivClearIcon.setImageResource(
|
ivClearIcon.setImageResource(
|
||||||
if (item.isOriginalData) R.drawable.ic_dish_clear
|
if (data.isOriginalData) R.drawable.ic_dish_clear
|
||||||
else R.drawable.ic_delete
|
else R.drawable.ic_delete
|
||||||
)
|
)
|
||||||
ivOperateIcon.setImageResource(
|
ivOperateIcon.setImageResource(
|
||||||
if (item.isSetFinished) R.drawable.ic_dish_selected
|
if (data.isSetFinished) R.drawable.ic_dish_selected
|
||||||
else R.drawable.ic_dish_unselected
|
else R.drawable.ic_dish_unselected
|
||||||
)
|
)
|
||||||
root.run {
|
clBlock.run {
|
||||||
setBackgroundResource(
|
setBackgroundResource(
|
||||||
if (item.isItemClicked) R.drawable.shape_item_cook_dish
|
if (data.isItemClicked) R.drawable.shape_item_cook_dish
|
||||||
else R.drawable.shape_white_fb_15_corners
|
else R.drawable.shape_white_fb_15_corners
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.chad.library.adapter4.viewholder.QuickViewHolder
|
|||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.databinding.ListItemFoodListBinding
|
import com.shuwei.dish.match.databinding.ListItemFoodListBinding
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.entity.FoodRecord
|
||||||
|
import com.shuwei.dish.match.view.swipereveallayout.ViewBinderHelper
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
@@ -34,6 +35,29 @@ class FoodListAdapter(
|
|||||||
SAMPLING_MODE
|
SAMPLING_MODE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 删除按钮点击回调,由外部(Activity/Fragment)设置 */
|
||||||
|
var onDeleteClick: ((position: Int) -> Unit)? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* item 主体点击回调,绑定在 mainView(clBlock)上,绕过 SwipeRevealLayout 的触摸拦截。
|
||||||
|
* 外部使用此回调替代 setOnDebouncedItemClick。
|
||||||
|
*/
|
||||||
|
var onItemClick: ((position: Int) -> Unit)? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewBinderHelper 负责:
|
||||||
|
* - 同一时间只允许一个 item 展开(setOpenOnlyOne)
|
||||||
|
* - RecyclerView 复用时恢复开合状态
|
||||||
|
*/
|
||||||
|
private val viewBinderHelper = ViewBinderHelper().apply {
|
||||||
|
setOpenOnlyOne(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭所有已展开的侧滑 item,供外部在点击空白区域时调用 */
|
||||||
|
fun closeAll() {
|
||||||
|
viewBinderHelper.closeAll()
|
||||||
|
}
|
||||||
|
|
||||||
inner class VH(var binding: ListItemFoodListBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemFoodListBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
@@ -51,6 +75,34 @@ class FoodListAdapter(
|
|||||||
val totalWeight = item.totalWeight ?: 0.0
|
val totalWeight = item.totalWeight ?: 0.0
|
||||||
val foodWeight = item.foodWeight ?: 0.0
|
val foodWeight = item.foodWeight ?: 0.0
|
||||||
|
|
||||||
|
// 用 foodId 作为唯一 key 恢复开合状态;不可滑动时锁定
|
||||||
|
val itemId = item.foodId ?: position.toString()
|
||||||
|
viewBinderHelper.bind(swipeRevealLayout, itemId)
|
||||||
|
if (isCooking) {
|
||||||
|
viewBinderHelper.unlockSwipe(itemId)
|
||||||
|
layoutDelete.visible()
|
||||||
|
} else {
|
||||||
|
viewBinderHelper.lockSwipe(itemId)
|
||||||
|
// 非烹饪中不允许侧滑,关闭可能的复用残留状态并隐藏删除按钮
|
||||||
|
swipeRevealLayout.close(false)
|
||||||
|
layoutDelete.gone()
|
||||||
|
}
|
||||||
|
// 绑定删除按钮回调
|
||||||
|
layoutDelete.setOnClickListener { onDeleteClick?.invoke(holder.bindingAdapterPosition) }
|
||||||
|
// 点击主内容区域:
|
||||||
|
// 1) 非烹饪中:先收起所有侧滑,再继续触发点击
|
||||||
|
// 2) 烹饪中:当前 item 若已展开则只收起,不触发点击
|
||||||
|
clBlock.setOnClickListener {
|
||||||
|
if (!isCooking) {
|
||||||
|
viewBinderHelper.closeAll()
|
||||||
|
onItemClick?.invoke(holder.bindingAdapterPosition)
|
||||||
|
} else if (!swipeRevealLayout.isClosed) {
|
||||||
|
viewBinderHelper.closeAll()
|
||||||
|
} else {
|
||||||
|
onItemClick?.invoke(holder.bindingAdapterPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tvDishName.text = item.foodName
|
tvDishName.text = item.foodName
|
||||||
//烹饪中
|
//烹饪中
|
||||||
if (isCooking) {
|
if (isCooking) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import androidx.activity.addCallback
|
|||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.DishPartAdapter
|
import com.shuwei.dish.match.adapter.DishPartAdapter
|
||||||
@@ -29,7 +28,6 @@ import com.shuwei.dish.match.utils.CameraUtils
|
|||||||
import com.shuwei.dish.match.utils.ImageUtil
|
import com.shuwei.dish.match.utils.ImageUtil
|
||||||
import com.shuwei.dish.match.utils.KeyboardUtil
|
import com.shuwei.dish.match.utils.KeyboardUtil
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
@@ -354,12 +352,29 @@ class PrepareFoodActivity : BaseActivity() {
|
|||||||
private val list = mutableListOf<CookFoodGoodsEntity>()
|
private val list = mutableListOf<CookFoodGoodsEntity>()
|
||||||
private val dishPartAdapter by lazy {
|
private val dishPartAdapter by lazy {
|
||||||
DishPartAdapter(list = list).apply {
|
DishPartAdapter(list = list).apply {
|
||||||
setOnItemClickListener { _, _, positon ->
|
val adapter = this
|
||||||
|
onItemClick = { positon ->
|
||||||
list.forEachIndexed { index, entity ->
|
list.forEachIndexed { index, entity ->
|
||||||
entity.isItemClicked = index == positon
|
entity.isItemClicked = index == positon
|
||||||
}
|
}
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
onDeleteClick = onDeleteClick@{ positon ->
|
||||||
|
Log.d(TAG, "onFoodItemClick: ${list[positon].toJsonString()}")
|
||||||
|
if (list[positon].isNewDishType.not()) {
|
||||||
|
toast("只能删除刚添加的食材")
|
||||||
|
return@onDeleteClick
|
||||||
|
}
|
||||||
|
CommonDialog(this@PrepareFoodActivity)
|
||||||
|
.setTitle("删除确认")
|
||||||
|
.setContent("确定删除食材「${list[positon].goodsName}」吗?")
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("删除") {
|
||||||
|
adapter.removeAt(positon)
|
||||||
|
toast("已删除")
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, positon ->
|
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, positon ->
|
||||||
Log.d(TAG, "onFoodItemClick: ${list[positon].toJsonString()}")
|
Log.d(TAG, "onFoodItemClick: ${list[positon].toJsonString()}")
|
||||||
if (list[positon].isOriginalData) {
|
if (list[positon].isOriginalData) {
|
||||||
@@ -371,7 +386,7 @@ class PrepareFoodActivity : BaseActivity() {
|
|||||||
notifyItemChanged(positon)
|
notifyItemChanged(positon)
|
||||||
return@addOnItemChildClickListener
|
return@addOnItemChildClickListener
|
||||||
}
|
}
|
||||||
removeAt(positon)
|
adapter.removeAt(positon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,16 +399,17 @@ class PrepareFoodActivity : BaseActivity() {
|
|||||||
layoutManager =
|
layoutManager =
|
||||||
LinearLayoutManager(this@PrepareFoodActivity, LinearLayoutManager.VERTICAL, false)
|
LinearLayoutManager(this@PrepareFoodActivity, LinearLayoutManager.VERTICAL, false)
|
||||||
adapter = dishPartAdapter
|
adapter = dishPartAdapter
|
||||||
val itemTouchHelper = ItemTouchHelper(SwipeCallback(dishPartAdapter) { position ->
|
addOnItemTouchListener(object : androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener() {
|
||||||
if (list[position].isNewDishType.not()) {
|
override fun onInterceptTouchEvent(
|
||||||
toast("只能删除刚添加的食材")
|
rv: androidx.recyclerview.widget.RecyclerView,
|
||||||
dishPartAdapter.notifyItemChanged(position)
|
e: android.view.MotionEvent
|
||||||
return@SwipeCallback
|
): Boolean {
|
||||||
|
if (e.action == android.view.MotionEvent.ACTION_DOWN) {
|
||||||
|
dishPartAdapter.closeAll()
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
dishPartAdapter.removeAt(position)
|
|
||||||
toast("已删除")
|
|
||||||
})
|
})
|
||||||
itemTouchHelper.attachToRecyclerView(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ 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 android.view.MotionEvent
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.FoodListAdapter
|
import com.shuwei.dish.match.adapter.FoodListAdapter
|
||||||
@@ -19,7 +19,6 @@ import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
|||||||
import com.shuwei.dish.match.dialog.CommonDialog
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.entity.FoodRecord
|
||||||
import com.shuwei.dish.match.utils.DateTimeUtil
|
import com.shuwei.dish.match.utils.DateTimeUtil
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
@@ -162,7 +161,24 @@ class SamplingModeActivity : BaseActivity() {
|
|||||||
private val dishAdapter by lazy {
|
private val dishAdapter by lazy {
|
||||||
FoodListAdapter(list = list, mode = FoodListAdapter.DisplayMode.SAMPLING_MODE).apply {
|
FoodListAdapter(list = list, mode = FoodListAdapter.DisplayMode.SAMPLING_MODE).apply {
|
||||||
isStateViewEnable = true
|
isStateViewEnable = true
|
||||||
setOnItemClickListener { adapter, view, position ->
|
onDeleteClick = { position ->
|
||||||
|
CommonDialog(this@SamplingModeActivity)
|
||||||
|
.setTitle("删除确认")
|
||||||
|
.setContent("确定要删除「${list[position].foodName}」吗?")
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("删除") {
|
||||||
|
deleteCookFoodAndGoods(foodId = list[position].foodId ?: "") {
|
||||||
|
if (list.size > 1) {
|
||||||
|
removeAt(position)
|
||||||
|
} else {
|
||||||
|
loadEmptyView()
|
||||||
|
}
|
||||||
|
toast("已删除")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
onItemClick = { position ->
|
||||||
judgeDeviceConfig {
|
judgeDeviceConfig {
|
||||||
onItemClick(position)
|
onItemClick(position)
|
||||||
}
|
}
|
||||||
@@ -192,22 +208,15 @@ class SamplingModeActivity : BaseActivity() {
|
|||||||
layoutManager =
|
layoutManager =
|
||||||
LinearLayoutManager(this@SamplingModeActivity, LinearLayoutManager.VERTICAL, false)
|
LinearLayoutManager(this@SamplingModeActivity, LinearLayoutManager.VERTICAL, false)
|
||||||
adapter = dishAdapter
|
adapter = dishAdapter
|
||||||
val itemTouchHelper = ItemTouchHelper(SwipeCallback(dishAdapter) { position ->
|
// 点击列表空白区域时关闭已展开的侧滑 item
|
||||||
if (list[position].isCooking.not()) {
|
addOnItemTouchListener(object : androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener() {
|
||||||
toast("只能删除烹饪中的菜品")
|
override fun onInterceptTouchEvent(rv: androidx.recyclerview.widget.RecyclerView, e: MotionEvent): Boolean {
|
||||||
dishAdapter.notifyItemChanged(position)
|
if (e.action == MotionEvent.ACTION_DOWN) {
|
||||||
return@SwipeCallback
|
dishAdapter.closeAll()
|
||||||
}
|
|
||||||
deleteCookFoodAndGoods(foodId = list[position].foodId ?: "") {
|
|
||||||
if (list.size > 1) {
|
|
||||||
dishAdapter.removeAt(position)
|
|
||||||
} else {
|
|
||||||
loadEmptyView()
|
|
||||||
}
|
}
|
||||||
toast("已删除")
|
return false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
itemTouchHelper.attachToRecyclerView(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ package com.shuwei.dish.match.ui.fragment
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.chad.library.adapter4.util.setOnDebouncedItemClick
|
|
||||||
import com.shuwei.dish.match.adapter.FoodListAdapter
|
import com.shuwei.dish.match.adapter.FoodListAdapter
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
import com.shuwei.dish.match.base.BaseFragment
|
import com.shuwei.dish.match.base.BaseFragment
|
||||||
@@ -17,11 +16,11 @@ import com.shuwei.dish.match.databinding.FragmentDishListBinding
|
|||||||
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
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.dialog.CommonDialog
|
||||||
import com.shuwei.dish.match.net.UiState
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.ui.PrepareFoodActivity
|
import com.shuwei.dish.match.ui.PrepareFoodActivity
|
||||||
import com.shuwei.dish.match.ui.CookingModeActivity
|
import com.shuwei.dish.match.ui.CookingModeActivity
|
||||||
import com.shuwei.dish.match.ui.SubmitFoodActivity
|
import com.shuwei.dish.match.ui.SubmitFoodActivity
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
@@ -54,12 +53,24 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
|
|||||||
private val dishAdapter by lazy {
|
private val dishAdapter by lazy {
|
||||||
FoodListAdapter(list = list).apply {
|
FoodListAdapter(list = list).apply {
|
||||||
isStateViewEnable = true
|
isStateViewEnable = true
|
||||||
setOnDebouncedItemClick { adapter, view, position ->
|
onDeleteClick = { position ->
|
||||||
if (isAdded.not() || isVisible.not()) {
|
CommonDialog(activity)
|
||||||
return@setOnDebouncedItemClick
|
.setTitle("删除确认")
|
||||||
}
|
.setContent("确定要删除「${list[position].foodName}」吗?")
|
||||||
activity.judgeDeviceConfig {
|
.setNegativeButton("取消")
|
||||||
onItemClick(position)
|
.setPositiveButton("删除") {
|
||||||
|
activity.deleteCookFoodAndGoods(foodId = list[position].foodId ?: "") {
|
||||||
|
removeAt(position)
|
||||||
|
activity.toast("已删除")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
onItemClick = { position ->
|
||||||
|
if (isAdded && isVisible) {
|
||||||
|
activity.judgeDeviceConfig {
|
||||||
|
onItemClick(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,18 +111,15 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
|
|||||||
layoutManager =
|
layoutManager =
|
||||||
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||||
adapter = dishAdapter
|
adapter = dishAdapter
|
||||||
val itemTouchHelper = ItemTouchHelper(SwipeCallback(dishAdapter) { position ->
|
// 点击列表空白区域时关闭已展开的侧滑 item
|
||||||
if (list[position].isCooking.not()) {
|
addOnItemTouchListener(object : androidx.recyclerview.widget.RecyclerView.SimpleOnItemTouchListener() {
|
||||||
activity.toast("只能删除烹饪中的菜品")
|
override fun onInterceptTouchEvent(rv: androidx.recyclerview.widget.RecyclerView, e: MotionEvent): Boolean {
|
||||||
dishAdapter.notifyItemChanged(position)
|
if (e.action == MotionEvent.ACTION_DOWN) {
|
||||||
return@SwipeCallback
|
dishAdapter.closeAll()
|
||||||
}
|
}
|
||||||
activity.deleteCookFoodAndGoods(foodId = list[position].foodId ?: "") {
|
return false
|
||||||
dishAdapter.removeAt(position)
|
|
||||||
activity.toast("已删除")
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
itemTouchHelper.attachToRecyclerView(this)
|
|
||||||
}
|
}
|
||||||
addViewListener()
|
addViewListener()
|
||||||
initObserver()
|
initObserver()
|
||||||
|
|||||||
+1133
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,271 @@
|
|||||||
|
/**
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Chau Thai
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.shuwei.dish.match.view.swipereveallayout;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewBinderHelper provides a quick and easy solution to restore the open/close state
|
||||||
|
* of the items in RecyclerView, ListView, GridView or any view that requires its child view
|
||||||
|
* to bind the view to a data object.
|
||||||
|
*
|
||||||
|
* <p>When you bind you data object to a view, use {@link #bind(SwipeRevealLayout, String)} to
|
||||||
|
* save and restore the open/close state of the view.</p>
|
||||||
|
*
|
||||||
|
* <p>Optionally, if you also want to save and restore the open/close state when the device's
|
||||||
|
* orientation is changed, call {@link #saveStates(Bundle)} in {@link android.app.Activity#onSaveInstanceState(Bundle)}
|
||||||
|
* and {@link #restoreStates(Bundle)} in {@link android.app.Activity#onRestoreInstanceState(Bundle)}</p>
|
||||||
|
*/
|
||||||
|
public class ViewBinderHelper {
|
||||||
|
private static final String BUNDLE_MAP_KEY = "ViewBinderHelper_Bundle_Map_Key";
|
||||||
|
|
||||||
|
private Map<String, Integer> mapStates = Collections.synchronizedMap(new HashMap<String, Integer>());
|
||||||
|
private Map<String, SwipeRevealLayout> mapLayouts = Collections.synchronizedMap(new HashMap<String, SwipeRevealLayout>());
|
||||||
|
private Set<String> lockedSwipeSet = Collections.synchronizedSet(new HashSet<String>());
|
||||||
|
|
||||||
|
private volatile boolean openOnlyOne = false;
|
||||||
|
private final Object stateChangeLock = new Object();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Help to save and restore open/close state of the swipeLayout. Call this method
|
||||||
|
* when you bind your view holder with the data object.
|
||||||
|
*
|
||||||
|
* @param swipeLayout swipeLayout of the current view.
|
||||||
|
* @param id a string that uniquely defines the data object of the current view.
|
||||||
|
*/
|
||||||
|
public void bind(final SwipeRevealLayout swipeLayout, final String id) {
|
||||||
|
if (swipeLayout.shouldRequestLayout()) {
|
||||||
|
swipeLayout.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
mapLayouts.values().remove(swipeLayout);
|
||||||
|
mapLayouts.put(id, swipeLayout);
|
||||||
|
|
||||||
|
swipeLayout.abort();
|
||||||
|
swipeLayout.setDragStateChangeListener(new SwipeRevealLayout.DragStateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onDragStateChanged(int state) {
|
||||||
|
mapStates.put(id, state);
|
||||||
|
|
||||||
|
if (openOnlyOne) {
|
||||||
|
closeOthers(id, swipeLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// first time binding.
|
||||||
|
if (!mapStates.containsKey(id)) {
|
||||||
|
mapStates.put(id, SwipeRevealLayout.STATE_CLOSE);
|
||||||
|
swipeLayout.close(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// not the first time, then close or open depends on the current state.
|
||||||
|
else {
|
||||||
|
int state = mapStates.get(id);
|
||||||
|
|
||||||
|
if (state == SwipeRevealLayout.STATE_CLOSE || state == SwipeRevealLayout.STATE_CLOSING ||
|
||||||
|
state == SwipeRevealLayout.STATE_DRAGGING) {
|
||||||
|
swipeLayout.close(false);
|
||||||
|
} else {
|
||||||
|
swipeLayout.open(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set lock swipe
|
||||||
|
swipeLayout.setLockDrag(lockedSwipeSet.contains(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only if you need to restore open/close state when the orientation is changed.
|
||||||
|
* Call this method in {@link android.app.Activity#onSaveInstanceState(Bundle)}
|
||||||
|
*/
|
||||||
|
public void saveStates(Bundle outState) {
|
||||||
|
if (outState == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bundle statesBundle = new Bundle();
|
||||||
|
for (Map.Entry<String, Integer> entry : mapStates.entrySet()) {
|
||||||
|
statesBundle.putInt(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
outState.putBundle(BUNDLE_MAP_KEY, statesBundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only if you need to restore open/close state when the orientation is changed.
|
||||||
|
* Call this method in {@link android.app.Activity#onRestoreInstanceState(Bundle)}
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "ConstantConditions"})
|
||||||
|
public void restoreStates(Bundle inState) {
|
||||||
|
if (inState == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (inState.containsKey(BUNDLE_MAP_KEY)) {
|
||||||
|
HashMap<String, Integer> restoredMap = new HashMap<>();
|
||||||
|
|
||||||
|
Bundle statesBundle = inState.getBundle(BUNDLE_MAP_KEY);
|
||||||
|
Set<String> keySet = statesBundle.keySet();
|
||||||
|
|
||||||
|
if (keySet != null) {
|
||||||
|
for (String key : keySet) {
|
||||||
|
restoredMap.put(key, statesBundle.getInt(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStates = restoredMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock swipe for some layouts.
|
||||||
|
* @param id a string that uniquely defines the data object.
|
||||||
|
*/
|
||||||
|
public void lockSwipe(String... id) {
|
||||||
|
setLockSwipe(true, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock swipe for some layouts.
|
||||||
|
* @param id a string that uniquely defines the data object.
|
||||||
|
*/
|
||||||
|
public void unlockSwipe(String... id) {
|
||||||
|
setLockSwipe(false, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param openOnlyOne If set to true, then only one row can be opened at a time.
|
||||||
|
*/
|
||||||
|
public void setOpenOnlyOne(boolean openOnlyOne) {
|
||||||
|
this.openOnlyOne = openOnlyOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a specific layout.
|
||||||
|
* @param id unique id which identifies the data object which is bind to the layout.
|
||||||
|
*/
|
||||||
|
public void openLayout(final String id) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
mapStates.put(id, SwipeRevealLayout.STATE_OPEN);
|
||||||
|
|
||||||
|
if (mapLayouts.containsKey(id)) {
|
||||||
|
final SwipeRevealLayout layout = mapLayouts.get(id);
|
||||||
|
layout.open(true);
|
||||||
|
}
|
||||||
|
else if (openOnlyOne) {
|
||||||
|
closeOthers(id, mapLayouts.get(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a specific layout.
|
||||||
|
* @param id unique id which identifies the data object which is bind to the layout.
|
||||||
|
*/
|
||||||
|
public void closeLayout(final String id) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
mapStates.put(id, SwipeRevealLayout.STATE_CLOSE);
|
||||||
|
|
||||||
|
if (mapLayouts.containsKey(id)) {
|
||||||
|
final SwipeRevealLayout layout = mapLayouts.get(id);
|
||||||
|
layout.close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭所有已展开的侧滑布局,用于点击空白区域时收起侧滑。
|
||||||
|
*/
|
||||||
|
public void closeAll() {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
for (Map.Entry<String, Integer> entry : mapStates.entrySet()) {
|
||||||
|
entry.setValue(SwipeRevealLayout.STATE_CLOSE);
|
||||||
|
}
|
||||||
|
for (SwipeRevealLayout layout : mapLayouts.values()) {
|
||||||
|
layout.close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close others swipe layout.
|
||||||
|
* @param id layout which bind with this data object id will be excluded.
|
||||||
|
* @param swipeLayout will be excluded.
|
||||||
|
*/
|
||||||
|
private void closeOthers(String id, SwipeRevealLayout swipeLayout) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
// close other rows if openOnlyOne is true.
|
||||||
|
if (getOpenCount() > 1) {
|
||||||
|
for (Map.Entry<String, Integer> entry : mapStates.entrySet()) {
|
||||||
|
if (!entry.getKey().equals(id)) {
|
||||||
|
entry.setValue(SwipeRevealLayout.STATE_CLOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SwipeRevealLayout layout : mapLayouts.values()) {
|
||||||
|
if (layout != swipeLayout) {
|
||||||
|
layout.close(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLockSwipe(boolean lock, String... id) {
|
||||||
|
if (id == null || id.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lock)
|
||||||
|
lockedSwipeSet.addAll(Arrays.asList(id));
|
||||||
|
else
|
||||||
|
lockedSwipeSet.removeAll(Arrays.asList(id));
|
||||||
|
|
||||||
|
for (String s : id) {
|
||||||
|
SwipeRevealLayout layout = mapLayouts.get(s);
|
||||||
|
if (layout != null) {
|
||||||
|
layout.setLockDrag(lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getOpenCount() {
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
for (int state : mapStates.values()) {
|
||||||
|
if (state == SwipeRevealLayout.STATE_OPEN || state == SwipeRevealLayout.STATE_OPENING) {
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#FFEF5350" />
|
||||||
|
<!-- 仅右侧两个角有圆角,与前景层圆角半径一致 -->
|
||||||
|
<corners
|
||||||
|
android:topRightRadius="15dp"
|
||||||
|
android:bottomRightRadius="15dp" />
|
||||||
|
</shape>
|
||||||
@@ -1,32 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- 白色垃圾桶图标:使用 evenOdd 填充规则实现条纹镂空,无硬编码背景色依赖 -->
|
<!-- 白色垃圾桶图标-->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="40dp"
|
android:width="24dp"
|
||||||
android:height="40dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="40"
|
android:viewportWidth="1024"
|
||||||
android:viewportHeight="40">
|
android:viewportHeight="1024">
|
||||||
|
|
||||||
<!-- 桶盖 -->
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFF"
|
android:fillColor="#FFFFFF"
|
||||||
android:fillType="evenOdd"
|
android:pathData="M913.5,225.8h-241V128c0,-34.5 -28.3,-62.8 -62.8,-62.8H413.3c-34.5,0 -62.8,28.3 -62.8,62.8v97.8H111.1c-25.8,0 -46.9,21.1 -46.9,46.9 0,25.8 21.1,46.9 46.9,46.9h81v590.3c0,25.8 21.1,46.9 46.9,46.9h546.4c25.8,0 46.9,-21.1 46.9,-46.9 0,-1.1 -0.1,-2.2 -0.1,-3.3V319.5h81.5c25.8,0 46.9,-21.1 46.9,-46.9 -0.2,-25.7 -21.3,-46.8 -47.1,-46.8zM448.1,156.1c0,-0.1 0,-0.1 0,0l128,-0.1s0.1,0 0.1,0.1v69.7h-128v-69.7zM737,863H287V319.5h450V863z" />
|
||||||
android:pathData="
|
|
||||||
M10,13 A1,1 0 0,1 10,11 L14,11 L14,9
|
|
||||||
A2,2 0 0,1 16,7 L24,7
|
|
||||||
A2,2 0 0,1 26,9 L26,11 L30,11
|
|
||||||
A1,1 0 0,1 30,13 Z
|
|
||||||
M16,9 L16,11 L24,11 L24,9 Z" />
|
|
||||||
|
|
||||||
<!-- 桶身:外轮廓 + 三条竖槽镂空,evenOdd 使竖槽透明 -->
|
|
||||||
<path
|
<path
|
||||||
android:fillColor="#FFFFFF"
|
android:fillColor="#FFFFFF"
|
||||||
android:fillType="evenOdd"
|
android:pathData="M420.8,767.8c27.4,0 49.8,-22.4 49.8,-49.8V466c0,-27.4 -22.4,-49.8 -49.8,-49.8S371,438.6 371,466v252c0,27.4 22.4,49.8 49.8,49.8zM602.9,767.8c27.4,0 49.8,-22.4 49.8,-49.8V466c0,-27.4 -22.4,-49.8 -49.8,-49.8s-49.8,22.4 -49.8,49.8v252c0,27.4 22.4,49.8 49.8,49.8z" />
|
||||||
android:pathData="
|
|
||||||
M12,15 L13.5,33
|
|
||||||
A2,2 0 0,0 15.5,35 L24.5,35
|
|
||||||
A2,2 0 0,0 26.5,33 L28,15 Z
|
|
||||||
M17,18 L17,32 L19,32 L19,18 Z
|
|
||||||
M19.5,18 L19.5,32 L21.5,32 L21.5,18 Z
|
|
||||||
M22,18 L22,32 L24,32 L24,18 Z" />
|
|
||||||
|
|
||||||
</vector>
|
</vector>
|
||||||
|
|
||||||
|
|||||||
@@ -1,85 +1,109 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.shuwei.dish.match.view.swipereveallayout.SwipeRevealLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/swipeRevealLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="120dp"
|
android:layout_height="120dp"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_marginEnd="30dp"
|
||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:background="@drawable/shape_white_fb_15_corners">
|
app:dragEdge="right">
|
||||||
|
|
||||||
<TextView
|
<FrameLayout
|
||||||
android:id="@+id/tvDishName"
|
android:id="@+id/layoutDelete"
|
||||||
android:layout_width="0dp"
|
android:layout_width="160dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="120dp"
|
||||||
android:layout_marginStart="30dp"
|
android:background="@drawable/bg_swipe_delete">
|
||||||
android:layout_marginEnd="30dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="@color/black"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/tvDishType"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/tvDishWeight"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="雪菜" />
|
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:id="@+id/tvDishType"
|
android:layout_width="48dp"
|
||||||
android:layout_width="0dp"
|
android:layout_height="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_gravity="center"
|
||||||
android:layout_marginTop="15dp"
|
android:contentDescription="删除"
|
||||||
android:ellipsize="end"
|
android:src="@drawable/ic_trash_white" />
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="@color/black999"
|
|
||||||
android:textSize="26sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
|
||||||
tools:text="主辅材:主材" />
|
|
||||||
|
|
||||||
<ImageView
|
</FrameLayout>
|
||||||
android:id="@+id/ivOperateIcon"
|
|
||||||
android:layout_width="80dp"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
tools:src="@drawable/ic_dish_selected"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/ivClearIcon"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<ImageView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/ivClearIcon"
|
android:id="@+id/clBlock"
|
||||||
android:layout_width="80dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="60dp"
|
android:layout_height="120dp"
|
||||||
android:src="@drawable/ic_delete"
|
android:background="@drawable/shape_white_fb_15_corners">
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvDishWeight"
|
android:id="@+id/tvDishName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_marginStart="30dp"
|
||||||
android:textColor="@color/dish_green"
|
android:layout_marginEnd="30dp"
|
||||||
android:textSize="32sp"
|
android:ellipsize="end"
|
||||||
android:textStyle="bold"
|
android:includeFontPadding="false"
|
||||||
android:hint="-"
|
android:maxLines="1"
|
||||||
android:textColorHint="@color/gray_d6"
|
android:textColor="@color/black"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/ivOperateIcon"
|
android:textSize="30sp"
|
||||||
app:layout_constraintEnd_toStartOf="@id/ivOperateIcon"
|
android:textStyle="bold"
|
||||||
app:layout_constraintTop_toTopOf="@id/ivOperateIcon"
|
app:layout_constraintBottom_toTopOf="@+id/tvDishType"
|
||||||
tools:text="375克"
|
app:layout_constraintEnd_toStartOf="@+id/tvDishWeight"
|
||||||
tools:ignore="HardcodedText" />
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:text="雪菜" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<TextView
|
||||||
|
android:id="@+id/tvDishType"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
||||||
|
tools:text="主辅材:主材" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivOperateIcon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/ivClearIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:src="@drawable/ic_dish_selected" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivClearIcon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:src="@drawable/ic_delete"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDishWeight"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:hint="-"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textColorHint="@color/gray_d6"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/ivOperateIcon"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/ivOperateIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/ivOperateIcon"
|
||||||
|
tools:ignore="HardcodedText"
|
||||||
|
tools:text="375克" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</com.shuwei.dish.match.view.swipereveallayout.SwipeRevealLayout>
|
||||||
|
|||||||
@@ -1,61 +1,87 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.shuwei.dish.match.view.swipereveallayout.SwipeRevealLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/clBlock"
|
android:id="@+id/swipeRevealLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="150dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="15dp"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginTop="7dp"
|
|
||||||
android:layout_marginEnd="15dp"
|
android:layout_marginEnd="15dp"
|
||||||
|
android:layout_marginTop="7dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:background="@drawable/shape_white_fb_15_corners"
|
app:dragEdge="right">
|
||||||
android:foreground="?android:attr/selectableItemBackground"
|
|
||||||
android:paddingStart="30dp"
|
|
||||||
android:paddingEnd="30dp">
|
|
||||||
|
|
||||||
<TextView
|
<!-- 后景层(secondaryView = getChildAt(0)):删除按钮,右对齐 -->
|
||||||
android:id="@+id/tvShowState"
|
<FrameLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/layoutDelete"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="160dp"
|
||||||
android:textColor="@color/black999"
|
android:layout_height="150dp"
|
||||||
android:textSize="32sp"
|
android:background="@drawable/bg_swipe_delete">
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="烹饪中" />
|
|
||||||
|
|
||||||
<TextView
|
<ImageView
|
||||||
android:id="@+id/tvDishName"
|
android:layout_width="48dp"
|
||||||
android:layout_width="0dp"
|
android:layout_height="48dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_gravity="center"
|
||||||
android:layout_marginEnd="20dp"
|
android:contentDescription="删除"
|
||||||
android:ellipsize="end"
|
android:src="@drawable/ic_trash_white" />
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="@color/dish_green"
|
|
||||||
android:textSize="32sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/tvDishCount"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/tvShowState"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
tools:text="冬虫夏草炝拌芥兰苗" />
|
|
||||||
|
|
||||||
<TextView
|
</FrameLayout>
|
||||||
android:id="@+id/tvDishCount"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textColor="@color/black999"
|
|
||||||
android:textSize="26sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
|
||||||
tools:text="累计统计:2.3kg(2次)" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<!-- 前景层(mainView = getChildAt(1)):item 主内容 -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/clBlock"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:background="@drawable/shape_white_fb_15_corners"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:paddingStart="30dp"
|
||||||
|
android:paddingEnd="30dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvShowState"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="烹饪中" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDishName"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/tvDishCount"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/tvShowState"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:text="冬虫夏草炝拌芥兰苗" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDishCount"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/tvDishName"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/tvDishName"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvDishName"
|
||||||
|
tools:text="累计统计:2.3kg(2次)" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</com.shuwei.dish.match.view.swipereveallayout.SwipeRevealLayout>
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<declare-styleable name="SwipeRevealLayout">
|
||||||
|
<attr name="dragEdge">
|
||||||
|
<flag name="left" value="1" />
|
||||||
|
<flag name="right" value="2" />
|
||||||
|
<flag name="top" value="4" />
|
||||||
|
<flag name="bottom" value="8" />
|
||||||
|
</attr>
|
||||||
|
|
||||||
|
<attr name="mode">
|
||||||
|
<enum name="normal" value="0" />
|
||||||
|
<enum name="same_level" value="1" />
|
||||||
|
</attr>
|
||||||
|
|
||||||
|
<attr name="flingVelocity" format="integer" />
|
||||||
|
|
||||||
|
<attr name="minDistRequestDisallowParent" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
||||||
Reference in New Issue
Block a user