개요
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 메소드에 체크박스의 정보를 가져와서 해시맵에 위치 값이 존재하면 체크상태로 변경합니다. 그 내부에 체크박스 클릭 리스너를 정의합니다. 체크하면 해시맵에 정보를 저장하고 해제하면 제외합니다.
직접 구현한 코드와 예제 코드의 스타일이 다를 수 있습니다. 그렇지만 체크박스의 정보를 저장하고 관리해야 한다는 것만 염두에 두시면 문제없이 기능을 구현하실 수 있을겁니다.