Search code examples
androidkotlinandroid-recyclerviewselecteditem

highlight the selected item of recyclerview


Please, don't mark it as duplicate I'm referring to this answer

Exception occurs:

kotlin.KotlinNullPointerException at package.name.ProductDetails.Custom_detail_Adapter.onBindViewHolder(Custom_detail_Adapter.kt:57)

This is the line:

holder.relativeitem.setSelected(selectedItems?.get(position, false)!!);

And also I would like to know how can setSelected at position first when loaded activity. (How to prepopulate SparseBooleanArray?)

Here is my adapter:

    class  Custom_detail_Adapter(context: Context, dataList: List<Product_images_response>) :
    RecyclerView.Adapter<Custom_detail_Adapter.CustomViewHolder>() {
    private val dataList: List<Product_images_response>
    private val context: Context
    private val selectedItems: SparseBooleanArray?=null

    inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),View.OnClickListener {
        val mView: View

         val avatar: ImageView
         val relativeitem:RelativeLayout

        init {
            mView = itemView

            avatar = mView.findViewById(R.id.view3)
            relativeitem=mView.findViewById(R.id.relativeitem)
        }

        override fun onClick(v: View?) {
            if (selectedItems?.get(getAdapterPosition(), false)!!) {
                selectedItems?.delete(getAdapterPosition());
                relativeitem.setSelected(false);
            }
            else {
                selectedItems?.put(getAdapterPosition(), true);
                relativeitem.setSelected(true);
            }
        }

    }

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

    override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
        holder.relativeitem.setSelected(selectedItems?.get(position, false)!!);

     Glide.with(context).load(dataList[position].image)
            .thumbnail(0.5f)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .into(holder.avatar)


        holder.avatar.setOnClickListener(View.OnClickListener {
           
            val intent = Intent("custom-message")
        
            intent.putExtra("item", dataList.get(position).image)
            LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
        })
    }

    override fun getItemCount(): Int {
        return dataList.size
        //return (dataList == null) ? 0 : dataList.size();
    }

    init {
        this.context = context
        this.dataList = dataList
    }
    }

Here is my layout:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:id="@+id/relativeitem"
    android:background="@drawable/activated_color_selector"
    android:layout_height="wrap_content">
    <ImageView
        android:layout_width="235px"
        android:layout_height="207px"
        android:id="@+id/view3"

        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_weight="1"
        />
        </RelativeLayout>

Need help! Thanks.


Solution

  • First of all, give an initial value to selectedItems variable. There is also no need to make it optional, thus eliminating the need to unwrap optional value with question mark (this selectedItems? becomes this selectedItems):

    private val selectedItems = SparseBooleanArray()
    

    If you want to set selected positions before the adapter is loaded make this variable one of the constructor arguments. With this primary constructor you can remove init block:

    class  Custom_detail_Adapter(private val context: Context, private val dataList: List<Product_images_response>, private val selectedItems: SparseBooleanArray) :
    RecyclerView.Adapter<Custom_detail_Adapter.CustomViewHolder>() {
    
    inner class CustomViewHolder ...
    

    This SparseBooleanArray constructor argument can be prepopulated with values that indicate which items are selected.