안드로이드

RecyclerView 선택을 커스터마이징하기

start1a 2019. 12. 31. 18:38

RecyclerView의 선택을 위해 Android Extension 패키지에서 지원하는 RecyclerView Selection 기능이 있다. 그러나 롱클릭의 경우에만 다중 선택이 가능하고 커스터마이징이 제한된다. 그래서 Adpater 내에 직접 구현하여 커스터마이징해 보려고 한다.

 

 

1. RecyclerView를 Layout에 붙이고 리스트의 아이템로 쓰일 Layout을 디자인

아래의 이전 RecyclerView 포스트에 설명해 두었다.

https://start1a.tistory.com/7

 

2. drawable 폴더에 Selector 생성

Selector는 View 조건에 따라 xml 참조하여 drawable 자동으로 변경해 주는 기능이다. 여기서는 View의 activate 속성의 true/false 에 따라 View의 배경 색상이 파랑과 흰색으로 바뀐다.

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item android:state_activated="true" android:drawable="@android:color/holo_blue_bright" />
    <item android:drawable="@android:color/white" />
</selector>
 
 

 

3. 리스트 아이템 Layout에서 Selector를 설정

2px 4px 0">cs

Layout의 속성에서 background를 찾음
아까 만든 Selector를 선택

 

 

4. ViewHolder 생성

이전 포스트에서 설명한 ViewHolder Class를 생성한다.

 

5. Adapter 생성

ViewHolder를 Adpater Class 파일 안에 넣었다. 

 

getItemId(position : Int) : View에 tag를 붙이기 위해 Id를 받았다. Id는 position 인덱스 번호를 그대로 쓰려고 한다.

selectionList : 선택한 리스트 position 번호가 저장되는 컬렉션.

onItemSelectionChangedListener : selectionList의 아이템 정보를 출력하기 위한 람다 함수.

 

onCreateViewHolder() : View의 onClickListener를 추가했다. 아이템 View 클릭 시 View에 기존에 저장했던 tag가 selectionList에 포함되어 있는지 확인하여 있으면 제거 없으면 추가하도록 분기하고 변경된 선택사항을 그려주기 위해 notify하였다. 출력할 람다 함수에 selectionList를 넣고 Activity에서 출력할 것이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class PersonAdapter (val list : List<Person>)
: RecyclerView.Adapter<PersonViewHolder>() {
 
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder {
        val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_person, parent, false)
        view.setOnClickListener(object : View.OnClickListener {
            override fun onClick(v: View?) {
                val id = v?.tag
                if (selectionList.contains(id)) selectionList.remove(id)
                else selectionList.add(id as Long)
                notifyDataSetChanged()
                onItemSelectionChangedListener?.let { it(selectionList) }
            }
 
        })
        return PersonViewHolder(view)
    }
 
    override fun getItemCount(): Int {
        return list.count()
    }
 
    override fun onBindViewHolder(holder: PersonViewHolder, position: Int) {
        holder.containerView.textName.text = list[position].name
        holder.containerView.textAge.text = list[position].age.toString()
        holder.containerView.tag = getItemId[position]
    }
// 아이템 id 반환
    override fun getItemId(position: Int): Long {
        return position.toLong()
    }
 
    val selectionList = mutableListOf<Long>()
    var onItemSelectionChangedListener : ((MutableList<Long>) -> Unit)? = null
}
 
class PersonViewHolder(override val containerView: View)
: RecyclerView.ViewHolder(containerView), LayoutContainer
 

 

 

 

6. 액티비티에서 연결

리스트 컬렉션을 만들고 adpter와 연결한다. 선택할 때마다 adapter에 선택된 ID 리스트가 출력된다. RecyclerView와 adapter를 연결하고 LinearLayout 형식으로 나열했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MainActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        val list = listOf(
            Person("a", 1),
            Person("b", 2),
            Person("c", 3),
            Person("d", 4),
            Person("e", 5)
        )
        val adapter = PersonAdapter(list)
        adapter.onItemSelectionChangedListener = {
            println("선택된 ID : $it")
        }
 
        personList.adapter = adapter
        personList.layoutManager = LinearLayoutManager(this)
    }
}
 
 

 

결과 화면

 

선택된 아이템
선택된 아이템 리스트를 Log에 출력
d, e 취소
3, 4가 사라짐