Swipe Delete Removing Different Item Kotlin

Viewed 43

I implemented Swipe to Delete Callback on my recyclerview in a Fragment, which the list of items are fetched from firestore. Whenever i swipe to delete an item after opening the app it works but when i try for the second time, it deletes a different item that i did not swiped or doesn't delete any item at all, sometimes the app ends up crashing.

Below is my Fragment

class AcademicFragment : BaseFragment() {

    // Override the onCreate function and add the piece of code to inflate the option menu in fragment.
    // START
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // If we want to use the option menu in fragment we need to add it.
        setHasOptionsMenu(true)
    }
    // END

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.fragment_academic, container, false)

        return root
    }
    // END

    // Override the onCreateOptionMenu function and inflate the Dashboard menu file init.
    // START
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.create_academic_cat_top_menu, menu)
        super.onCreateOptionsMenu(menu, inflater)

    }
    // END


    //  Override the onOptionItemSelected function and handle the action items init.
    // START
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val id = item.itemId

        when (id) {

            R.id.action_create_academic_cat -> {

                // Launch the Create Personal Category Activity on click of action item.
                // START
                startActivity(Intent(activity, CreateAcademicCategoryActivity::class.java))
                // END
                return true
            }

        }
        return super.onOptionsItemSelected(item)
    }
    // END

    override fun onResume() {
        super.onResume()

        getAcategoryListFromFireStore()
    }


    //Getting the list by call the  firestore class
    private fun getAcategoryListFromFireStore() {
        // Show the progress dialog.
        showProgressDialog(resources.getString(R.string.please_wait))

        // Call the function of Firestore class.
        FirestoreClass().getAcademicCategoryList(this@AcademicFragment)
    }

    fun successAcademicListFromFireStore(acategoryList: ArrayList<AcademicCategory>) {

        // Hide Progress dialog.
        hideProgressDialog()
        if (acategoryList.size > 0) {
            rv_my_acadCate_items.visibility = View.VISIBLE
            tv_no_acadCate_found.visibility = View.GONE

            rv_my_acadCate_items.layoutManager = LinearLayoutManager(activity)
            rv_my_acadCate_items.setHasFixedSize(true)


            val adapterAcadmicCates =
                MyAcademicCategoryListAdapter(
                    requireActivity(),
                    acategoryList,
                    this@AcademicFragment
                )
            // END
            rv_my_acadCate_items.adapter = adapterAcadmicCates

            val editSwipeHandler = object : SwipeToEditCallback(requireActivity()) {
                override fun  onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    val adapter = rv_my_acadCate_items.adapter as MyAcademicCategoryListAdapter
                    adapter.notifyEditItem(
                        this@AcademicFragment,
                        viewHolder.adapterPosition
                    )


                }
            }
            val editItemTouchHelper = ItemTouchHelper(editSwipeHandler)
            editItemTouchHelper.attachToRecyclerView(rv_my_acadCate_items)

//SwipeToDelete
            val deleteSwipeHandler = object : SwipeToDeleteCallback(requireActivity()) {
                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {



                    // Show the progress dialog.
                    showProgressDialog(resources.getString(R.string.please_wait))

                    FirestoreClass().deletePcate(
                        this@AcademicFragment,
                        acategoryList.removeAt(viewHolder.adapterPosition).academic_category_id

                    )


                }
            }
            val deleteItemTouchHelper = ItemTouchHelper(deleteSwipeHandler)
            deleteItemTouchHelper.attachToRecyclerView(rv_my_acadCate_items)






        } else {
            rv_my_acadCate_items.visibility = View.GONE
            tv_no_acadCate_found.visibility = View.VISIBLE
        }

    }

    fun deletePCatesuccess() {

        // Hide progress dialog.
        hideProgressDialog()

        Toast.makeText(
            requireActivity(),
            resources.getString(R.string.err_your_pcate_deleted_successfully),
            Toast.LENGTH_SHORT
        ).show()

        getAcategoryListFromFireStore()
    }


}

Below is My Firestore Delete method

 fun deletePcate(fragment: AcademicFragment, acadcatedetId: String) {

        mFireStore.collection(Constants.ACADCATEGORY)
            .document(acadcatedetId)
            .delete()
            .addOnSuccessListener {

                // Here call a function of base activity for transferring the result to it.
                fragment.deletePCatesuccess()
            }
            .addOnFailureListener { e ->
                fragment.hideProgressDialog()
                Log.e(
                    fragment.javaClass.simpleName,
                    "Error while deleting the Personal Category.",
                    e
                )
            }
    }

Below is my Swipe Delete Callback class

abstract class SwipeToDeleteCallback(context: Context) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {

    private val deleteIcon = ContextCompat.getDrawable(context, R.drawable.ic_vector_delete_24)
    private val intrinsicWidth = deleteIcon!!.intrinsicWidth
    private val intrinsicHeight = deleteIcon!!.intrinsicHeight
    private val background = ColorDrawable()
    private val backgroundColor = Color.parseColor("#f44336")
    private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }


    override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
        /**
         * To disable "swipe" for specific item return 0 here.
         * For example:
         * if (viewHolder?.itemViewType == YourAdapter.SOME_TYPE) return 0
         * if (viewHolder?.adapterPosition == 0) return 0
         */
        if (viewHolder.adapterPosition == 10) return 0
        return super.getMovementFlags(recyclerView, viewHolder)
    }

    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        return false
    }

    override fun onChildDraw(
            c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
            dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean
    ) {

        val itemView = viewHolder.itemView
        val itemHeight = itemView.bottom - itemView.top
        val isCanceled = dX == 0f && !isCurrentlyActive

        if (isCanceled) {
            clearCanvas(c, itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat())
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            return
        }

        // Draw the red delete background
        background.color = backgroundColor
        background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
        background.draw(c)

        // Calculate position of delete icon
        val deleteIconTop = itemView.top + (itemHeight - intrinsicHeight) / 2
        val deleteIconMargin = (itemHeight - intrinsicHeight) / 2
        val deleteIconLeft = itemView.right - deleteIconMargin - intrinsicWidth
        val deleteIconRight = itemView.right - deleteIconMargin
        val deleteIconBottom = deleteIconTop + intrinsicHeight

        // Draw the delete icon
        deleteIcon!!.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom)
        deleteIcon.draw(c)

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
    }

    private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) {
        c?.drawRect(left, top, right, bottom, clearPaint)
    }
}

Below is the Adapter

open class MyAcademicCategoryListAdapter(
    private val context: Context,
    private var list: ArrayList<AcademicCategory>,
    private val fragment: AcademicFragment
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// END

    /**
     * Inflates the item views which is designed in xml layout file
     *
     * create a new
     * {@link ViewHolder} and initializes some private fields to be used by RecyclerView.
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return MyViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.item_list_academic_categories_layout,
                parent,
                false
            )
        )
    }




    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val model = list[position]

        if (holder is MyViewHolder) {


            holder.itemView.tv_cate_name.text = model.academic_category_title

            // END
            holder.itemView.setOnClickListener {
                // Launch Academic Folder Screen details screen.
                val intent = Intent(context, AcademicFolderActivity::class.java)
                intent.putExtra(Constants.EXTRA_ACADEMIC_CATEGOTY_ID, model.academic_category_id)
                context.startActivity(intent)
            }
        }
    }


    /**
     * Gets the number of items in the list
     */
    override fun getItemCount(): Int {
        return list.size
    }




    fun notifyEditItem(activity: AcademicFragment, position: Int) {
        val intent = Intent(context, CreateAcademicCategoryActivity::class.java)
        intent.putExtra(Constants.EXTRA_ACADCATEGORY_DETAILS, list[position])
        activity.startActivity(intent)
        notifyItemChanged(position) // Notify any registered observers that the item at position has changed.
    }





    /**
     * A ViewHolder describes an item view and metadata about its place within the RecyclerView.
     */
    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
0 Answers
Related