Hassan
Hassan

Reputation: 500

position of recyclerview item changes after opening the fragment again

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

Answers (1)

Hassan
Hassan

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

Related Questions