본문 바로가기

Android/UI

[안드로이드] 하나만 선택 가능한 체크박스 리사이클러뷰 만들기

728x90
반응형

 

체크박스는 선택/선택해제 두가지만 있습니다.

이를 리사이클러 뷰 내에서 하나만 선택 가능하고, 리사이클러 뷰 스크롤 시에도 유지되어야 합니다.

추가적으로, 리사이클러뷰에 데이터 바인딩을 이용해,

체크박스가 선택되었을때/선택 해제되었을때의 배경과 색을 커스텀 하였고, 클릭 리스너도 추가 하였습니다.

 

  • background_cb_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid
        android:color="#3A27A2"/>
    <corners
        android:radius="@dimen/_2dp" />
    <stroke
        android:width="@dimen/_3dp"
        android:color="#D7C7F2" />
</shape>

 

  • background_white.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="@color/white" />
    <corners
        android:radius="0dp" />
</shape>

 

  • item_cb.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" >
    <data>
        <import type="android.view.View" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/_5dp"
        android:orientation="horizontal">
        <CheckBox
            android:id="@+id/item_cb"
            android:layout_width="match_parent"
            android:layout_height="@dimen/_35dp"
            android:background="@{itemCb.checked?@drawable/background_cb_selected:@drawable/background_white}"
            android:button="@null"
            android:gravity="center"
            android:textColor="@{itemCb.checked?@color/white:@color/black}"
            android:textSize="@dimen/_14dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

  • CbListAdapter.kt
class CbListAdapter: RecyclerView.Adapter<CbListAdapter.CbListViewHolder>() {

    private var items: List<CbItem> = ArrayList()
    private lateinit var itemClickListner: ItemClickListener

    private var mSelectedItem = -1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CbListViewHolder =
        CbListViewHolder(ItemCbBinding.inflate(LayoutInflater.from(parent.context),parent,false))


    override fun onBindViewHolder(holder: CbListViewHolder, position: Int) {
        holder.bind(items[position], position)
    }

    override fun getItemCount(): Int = items.size


    fun setItem(item: List<CbItem>) {
        items = item
        mSelectedItem = -1
        notifyDataSetChanged()
    }

    inner class CbListViewHolder(private val binding: ItemCbBinding): RecyclerView.ViewHolder(binding.root){
        fun bind(item: CbItem, position: Int) {
            val checkBox = binding.itemCb
            checkBox.text = item.title
            checkBox.isChecked = position == mSelectedItem

            checkBox.setOnClickListener {
                mSelectedItem = position
                itemClickListner.onClick(it,item)
                notifyItemRangeChanged(0, items.size)
            }

        }
    }

    interface ItemClickListener {
        fun onClick(view: View, cbItem: CbItem)
    }
    fun setItemClickListener(itemClickListener: ItemClickListener) {
        this.itemClickListner = itemClickListener
    }
}

 

  • MainActivity.kt
private lateinit var cbListAdapter: CbListAdapter
...

// init
cbListAdapter = CbListAdapter()

val layoutManager = GridLayoutManager(this),2)
with(binding) {
     rvCbList.apply {
          setHasFixedSize(true)
          this.layoutManager = layoutManager
          adapter = cbListAdapter
     }
}

// set item
cbListAdapter.setItem(ArrayList())

// click listener
cbListAdapter.setItemClickListener(object : CbListAdapter.ItemClickListener {
     override fun onClick(view: View, cbItem: CbItem) {
            // todo : click
      }
 })

 

끝!^^

728x90
반응형