Android RecyclerView 체크박스 상태 관리

개요

Android RecyclerView 는 화면에 보여지는 영역에서만 정의된 항목들이 유효합니다. 스크롤되어 다른 자료가 보여지게 되면 이전에 적용된 속성이 사라지게 됩니다. 대표적인 예가 체크박스 상태입니다. 화면에 보여질 때 체크하고 스크롤 후 다시 그 자료로 돌아와 보면 체크되지 않는 상태로 됩니다. 그래서 체크된 자료를 대상으로 처리하거나 전체선택/해제 기능을 구현할 때 이런 특성을 알고 있어야 합니다. 이번글에서는 전체선택/해제, 체크박스의 상태 유지 기능을 구현하는 방법을 알아보도록 하겠습니다.

체크박스 상태 저장

어디에선가는 체크박스 상태를 저장하고 있어야 합니다. 몇번째 체크박스가 체크되어 있는지에 관한 정보가 될 것입니다. 이글에서는 해시맵(Hashmap)을 이용해서 체크박스 상태를 저장해 보도록 하겠습니다. 다음과 같이 해시맵을 선언합니다. 리스트자료의 고유값을 키(Key)로 하고 값(Value)은 위치(Position) 값으로 저장해 보겠습니다.

companion object {
    lateinit var selectCheckBoxPosition:HashMap<Int, Int>
    private set
}

전체선택/해제

먼저 체크박스를 전체 선택하는 체크박스가 정의되어 있고 그것을 클릭했을 때 전체선택/해제 정보를 해시맵에 할당해 보겠습니다.

viewBinding.checkAllCheckBox.setOnClickListener {
    selectCheckBoxPosition.clear()
    if (viewBinding.checkAllCheckBox.isChecked) {
        for ((index, listData:yourClass) in yourList.withIndex()) {
            selectCheckBoxPosition[listData.Seq] = index
        }
    }
    listAdapter.notifyDataSetChanged()
}

체크박스를 클릭하면 해시맵을 비웁니다. 체크가 되었다면 연결된 리스트의 자료를 대상으로 고유값을 키로해서 위치 정보를 저장합니다. 그 다음 어댑터에 자료가 변경되었다는 것을 알립니다.

체크된 항목 정보 저장

전체선택/해제와 방식은 비슷합니다. 리스트내의 체크박스를 체크하면 해시맵에 저장하고 해제하면 제외합니다.

override fun onBindViewHolder(holder: Holder, position: Int) {
    holder.bind(yourList[position])
    val seqCheckBox = holder.itemView.findViewById<CheckBox>(R.id.seq)
    seqCheckBox.setOnCheckedChangeListener(null)
    seqCheckBox.isChecked = yourActivity.selectCheckBoxPosition.containsValue(position)
    seqCheckBox.setOnClickListener {
        val seq = seqCheckBox.tag.toString().toInt()
        if (seqCheckBox.isChecked) {
            yourActivity.selectCheckBoxPosition[seq] = position
        } else {
            yourActivity.selectCheckBoxPosition.remove(seq)
        }
    }
}

onBindViewHolder 메소드에 체크박스의 정보를 가져와서 해시맵에 위치 값이 존재하면 체크상태로 변경합니다. 그 내부에 체크박스 클릭 리스너를 정의합니다. 체크하면 해시맵에 정보를 저장하고 해제하면 제외합니다.

직접 구현한 코드와 예제 코드의 스타일이 다를 수 있습니다. 그렇지만 체크박스의 정보를 저장하고 관리해야 한다는 것만 염두에 두시면 문제없이 기능을 구현하실 수 있을겁니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다

Time limit is exhausted. Please reload the CAPTCHA.