Reputation: 500
I am using android kotlin. i am working on online shopping app.
in the shopping cart section. all things works fine.adding an item to cart or delete the item or adding quantity and undoing the delete .
when i click on undo button the item is placed in its own position after undoing the deleted item. but when i close the fragment and open it again all item position changes and the item that i clicked first will be first item and so to the end
this is my recycler adapter:
class BasketRecyclerAdapter(val list: MutableList<Model.BasketItem>, val listener: ButtonListener) :
RecyclerView.Adapter<BasketRecyclerAdapter.ViewHolder>() {
lateinit var context: Context
lateinit var localStore: LocalStore // i saved user phone and pass in a shared prefs using this class
inner class ViewHolder(val binding: BasketItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BasketRecyclerAdapter.ViewHolder {
val binding: BasketItemLayoutBinding = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.basket_item_layout,
parent,
false
)
localStore = LocalStore(parent.context)
context = parent.context
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: BasketRecyclerAdapter.ViewHolder, position: Int) {
val currentItem = list[position]
holder.binding.apply {
title.text = currentItem.title
numberPicker.progress = currentItem.quantity
color.setCardBackgroundColor(android.graphics.Color.parseColor(currentItem.color))
colorName.text = currentItem.color_name
price.text =
doubleToStringNoDecimal((currentItem.price * currentItem.quantity).toDouble())
Glide.with(context)
.asBitmap()
.load(currentItem.url)
.into(productImage)
holder.binding.apply {
numberPicker.doOnProgressChanged { numberPicker, progress, formUser ->
listener.onPickerProgressChanged(
numberPicker,
progress,
formUser,
position
)
price.text =
doubleToStringNoDecimal((currentItem.price * progress).toDouble())
}
delete.setOnClickListener {
listener.delete(holder.adapterPosition)
removeItem(holder.adapterPosition, holder)
}
}
}
}
override fun getItemCount(): Int = list.size
fun doubleToStringNoDecimal(d: Double): String? {
val formatter: DecimalFormat = NumberFormat.getInstance(Locale.US) as DecimalFormat
formatter.applyPattern("#,###,###,###")
return formatter.format(d)
}
fun removeItem(position: Int, viewHolder: RecyclerView.ViewHolder) {
val removedItem = list[position]
val removedPosition = position
list.removeAt(position)
notifyItemRemoved(position)
val snackbar = Snackbar.make(
viewHolder.itemView,
"این کالا از سبد خرید حذف شد",
Snackbar.LENGTH_LONG
)
snackbar.setAction("بازگرداندن") {
list.add(removedPosition, removedItem)
notifyItemInserted(removedPosition)
listener.SnackActionClicked(position)
}
snackbar.setActionTextColor(Color.YELLOW);
snackbar.show();
}
interface ButtonListener {
fun onPickerProgressChanged(
numberPicker: NumberPicker,
progress: Int,
fromUser: Boolean,
position: Int
)
fun delete(position: Int)
fun SnackActionClicked(position: Int)
}
}
adapter =
BasketRecyclerAdapter(
items as ArrayList<Model.BasketItem>,
object : BasketRecyclerAdapter.ButtonListener {
override fun onPickerProgressChanged(
numberPicker: NumberPicker,
progress: Int,
fromUser: Boolean,
position: Int
) {
val currentitem = items[position]
viewModel.AddToCart(
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
progress,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
updateWorkerData(
currentitem.title,
currentitem.color,
Model.BasketItem::quantity,
progress
)
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
override fun delete(position: Int) {
val currentitem = items[position]
viewModel.DeleteItemInCart(
localStore.getMobile().toString(),
currentitem.title,
currentitem.color_name
)
itemList.remove(
Model.BasketItem(
currentitem.id,
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
currentitem.quantity,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
)
if (items.size == 1)
if (isLastVisible()) {
basketpic.visibility = View.VISIBLE
emptyBasketText.visibility = View.VISIBLE
} else {
basketpic.visibility = View.GONE
emptyBasketText.visibility = View.GONE
}
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
override fun SnackActionClicked(position: Int) {
val currentitem = items[position]
viewModel.AddToCart(
localStore.getMobile().toString(),
currentitem.category,
currentitem.title,
currentitem.url,
currentitem.price,
currentitem.quantity,
currentitem.color,
currentitem.color_name,
currentitem.product_id
)
binding.apply {
basketpic.visibility = View.GONE
emptyBasketText.visibility = View.GONE
}
viewModel.CalculateTotalPrice(items)
.observe(viewLifecycleOwner) {
binding.price.text = doubleToStringNoDecimal(it)
}
}
})
any help will be appreciated
UPDATE
you can see that first one is white and the second is brown but when i delete and undodelete the brown then white and reopen the fragment their position changes-> see second picture
after delete and undo deleteitems(first brown then white) and reopening the fragment
Upvotes: 1
Views: 767
Reputation: 500
The Problem was that when i Clicked on Delete button the corresponding row in the Mysql was deleted and when i Clicked on Undo button the items that i deleted them
Were added to the table with new id and beacause of this the position of item changed after the fragment reopened
so i set a Snackbar.Callback to snackbar and i said that when it closed on its own then you can delete the item from database(mysql)
this is the code:
val snackbar = Snackbar.make(
viewHolder.itemView,
"این کالا از سبد خرید حذف شد",
Snackbar.LENGTH_LONG
)
snackbar.setAction("بازگرداندن") {
list.add(removedPosition, removedItem)
listener.SnackActionClicked(position)
notifyItemInserted(removedPosition)
}
snackbar.setActionTextColor(Color.YELLOW);
snackbar.addCallback(object : Snackbar.Callback() {
override fun onDismissed(snackbar: Snackbar?, event: Int) {
super.onDismissed(snackbar, event)
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
// Snackbar closed on its own
// Delete item from mysql database
}
}
override fun onShown(snackbar: Snackbar?) {
super.onShown(snackbar)
}
});
snackbar.show();
Upvotes: 1