user12180120
user12180120

Reputation:

How to make delete button to delete recyclerview items in kotlin?

I made selectDelete button on the main activity instead of RecyclerView. When I click that button, I want to delete the items which are checked. There is an error that checks the RecyclerView item checkbox and unchecks the item when scrolling.


Activity

class CartViewActivity : AppCompatActivity(), SwipeRefreshLayout.OnRefreshListener {

    private val tag = this::class.java.simpleName

    lateinit var adapter: CartItemRecyclerAdapter

    var itemList: MutableList<CartItemDataVo> = arrayListOf()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cart_view)

        selectDelete.setOnClickListener {

            if (checkBox.isChecked) {
                  *adapter.removeItems()*
            }
        }

        swipeRefreshLo.setOnRefreshListener(this)

        itemList.add(CartItemDataVo("item1", 1, 16800, "cart_doll", false))
        itemList.add(CartItemDataVo("item2", 1, 16800, "cart_cup", false))
        itemList.add(CartItemDataVo("item3", 1, 30000, "cart_perfume", false))
        itemList.add(CartItemDataVo("item4", 1, 16800, "cart_fan", false))

        adapter = CartItemRecyclerAdapter(this, this, itemList)
        recycler_view.adapter = adapter
        recycler_view.layoutManager =
            androidx.recyclerview.widget.LinearLayoutManager(applicationContext)
    }

    override fun onRefresh() {
        swipeRefreshLo.isRefreshing = false
    }
}

Adapter:

class CartItemDataVo(
    title: String,
    itemNumber: Int,
    pointValue: Int,
    imageView: String,
    CheckBox: Boolean
) {
    var title: String = title
    var itemNumber: Int = itemNumber
    var pointValue: Int = pointValue
    var image: String = imageView
    var isChecked: Boolean = CheckBox
}

class CartItemRecyclerAdapter(
    val context: Context,
    private var activity: Activity,
    private var dataList: MutableList<CartItemDataVo>
) : RecyclerView.Adapter<CartItemRecyclerAdapter.Holder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val view = LayoutInflater.from(context).inflate(R.layout.cart_item_list, parent, false)
        return Holder(view)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder?.bind(dataList[position], context)
    }

    override fun getItemCount(): Int = dataList.size


    *@SuppressLint("NewApi")
    fun removeItems() {
        dataList.removeIf { it.isChecked }
        notifyDataSetChanged()
     }*

    fun toggleItems() {
        for (item: CartItemDataVo in dataList) {
            var state = item.isChecked
            item.isChecked = state.not()
        }
        notifyDataSetChanged()
    }

    inner class Holder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {

        var titleText = itemView?.findViewById(R.id.titleText) as TextView
        var temNumerTextt = itemView?.findViewById(R.id.textViewItemNumer) as TextView
        var pointValueText = itemView?.findViewById(R.id.pointValueText) as TextView
        var imageView = itemView?.findViewById(R.id.imageView) as ImageView
        var checkBox = itemView?.findViewById(R.id.checkBox) as CheckBox

        fun bind(data: CartItemDataVo, context: Context) {
            if (data.image != "") {
                val resourceId =
                    context.resources.getIdentifier(data.image, "drawable", context.packageName)
                imageView?.setImageResource(resourceId)
            } else {
                imageView.setImageResource(R.mipmap.ic_launcher)
            }
            titleText?.text = data.title
            temNumerTextt?.text = data.itemNumber.toString()
            pointValueText?.text = data.pointValue.toString() + "P"

            if (data.isChecked) {
                checkBox.buttonDrawable =
                    checkBox.context.getDrawable(R.drawable.check_box_active_cs)
                val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
                layout.visibility = View.VISIBLE
            } else {
                checkBox.buttonDrawable = checkBox.context.getDrawable(R.drawable.check_box_no)
                val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
                layout.visibility = View.GONE
            }


            checkBox?.setOnClickListener {
                if (checkBox.isChecked == data.isChecked) {
                    checkBox.buttonDrawable = it.context.getDrawable(R.drawable.check_box_active_cs)
                    val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
                    layout.visibility = View.VISIBLE
                } else {
                    checkBox.buttonDrawable = it.context.getDrawable(R.drawable.check_box_no)
                    val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout
                    layout.visibility = View.GONE
                }

            }
        }
    }
}

Upvotes: 0

Views: 3523

Answers (1)

Damian Kozlak
Damian Kozlak

Reputation: 7083

First of all, replace

var itemList: MutableList<CartItemDataVo> = arrayListOf()

with

val itemList: MutableList<CartItemDataVo> = arrayListOf()

You don't want mutable property, which is also mutable collection at the same time. This is very bad practice.

Same situation in adapter

private var dataList : MutableList<CartItemDataVo>

replace with

private val dataList : MutableList<CartItemDataVo>


Then remove private var activity : Activity from your adapter's constructor. Don't put any references to Activity or Fragment in adapter!

Adapter should be only responsible for displaying list.

If in any case, you need communication between Activity or Fragment and adapter, use interface instead. This is not ViewHolder responsibility to hold reference to parent layout and manipulate it!

val layout = activity?.findViewById(R.id.layoutOrder) as LinearLayout

All lines like below should be removed from ViewHolder. If you need set something which belongs to Activity, based on action on list, use interface.


Finally, in adapter add method which will remove checked items from it:

fun removeItems() {
    itemList.removeIf { it.isChecked }
    notifyDataSetChanged()
}

Add the following line right after checkBox?.setOnClickListener { (as first line in listener)

data.isChecked = !data.isChecked

And replace

selectDelete.setOnClickListener {

    if(checkBox.isChecked){


    }
}

with

selectDelete.setOnClickListener {

    if(checkBox.isChecked){
        adapter?.removeItems()
    }
}

Bonus:

  • read about data class, and use it for CartItemDataVo (don't use CheckBox in constructor),

  • updateData method can be optimized using DiffUtil for RecyclerView,

  • it can be improved by modifying data in Activity, not in adapter, so responsible would be moved to better place,

  • read about SOLID principles,

  • read about MVVM and MVP design patterns.

Upvotes: 3

Related Questions