최근에 RecyclerView 를 사용할 때 단일 선택을 할 수 있도록 해야 되는 상황이 있었어요.
머리로는 간단하다고 생각 들면서도... 뇌정지가 왔어요.
ListView 같은 경우는 속성 값으로 choicemode 가 있는데 RecyclerView 는 따로 없더라구요.
간단하게 정리해놓으면 좋을 것 같아서 남기게 되었습니다.
1. MainActivity
xml 에 정의한 rvItemList 를 초기화해주고, 아이템을 adapter 에 전달해 줍니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// RecyclerView Initialize
val rvItemList = findViewById<RecyclerView>(R.id.rvItemList)
val decoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
val mLayoutManager = LinearLayoutManager(this)
mLayoutManager.orientation = LinearLayoutManager.VERTICAL
rvItemList.layoutManager = mLayoutManager
rvItemList.setHasFixedSize(true)
rvItemList.itemAnimator = DefaultItemAnimator()
rvItemList.addItemDecoration(decoration)
// RecyclerView ItemList
val itemList = ArrayList<String>()
itemList.add("1")
itemList.add("2")
itemList.add("3")
itemList.add("4")
itemList.add("5")
// RecyclerView Update
rvItemList.adapter = ItemAdapter(itemList)
}
2. ItemAdapter
ItemList 를 전달받고 Adapter 에서 선택한 Item 에 대한 ClickListener 를 정의해주고,
각각의 Item UI 도 업데이트 해줍니다.
선택된 UI 는 단순하게 색깔로 표시하려고 합니다. (selected : GREEN / unselected : WHITE)
마지막으로 아이템을 클릭할 때마다 선택된 아이템 로그를 확인할 수 있습니다.
class ItemAdapter(private var itemList: ArrayList<String>) : RecyclerView.Adapter<ItemAdapter.RecyclerViewHolder?>() {
private var selectedItemPosition = -1
private var selectedLayout: LinearLayout? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_item, parent, false)
return RecyclerViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
val lyItem = holder.itemView.findViewById<LinearLayout>(R.id.lyItem)
val text = itemList[position]
// Item Initialize
if (position == selectedItemPosition) {
lyItem.setBackgroundColor(Color.GREEN)
} else {
lyItem.setBackgroundColor(Color.WHITE)
}
// Item ClickListener
lyItem.setOnClickListener {
val currentPosition = holder.adapterPosition
if (selectedItemPosition == currentPosition) {
// Item Already Selected
selectedItemPosition = -1
selectedLayout?.setBackgroundColor(Color.WHITE)
selectedLayout = null
} else {
// Item New Selected
if (selectedItemPosition >= 0 || selectedLayout != null) {
selectedLayout?.setBackgroundColor(Color.WHITE)
}
selectedItemPosition = currentPosition
selectedLayout = lyItem
selectedLayout?.setBackgroundColor(Color.GREEN)
}
Log.d("ItemAdapter", "getSelectedItem = " + getSelectedItem())
}
holder.updateViewHolder(text)
}
override fun getItemCount(): Int {
return itemList.size
}
fun getItemList(): ArrayList<String> {
return itemList
}
fun getSelectedItem(): String? {
return if (selectedItemPosition >= 0)
itemList[selectedItemPosition]
else null
}
class RecyclerViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
fun updateViewHolder(text: String) {
val tvItem = view.findViewById<TextView>(R.id.tvItem)
tvItem.text = text
}
}
}
3. 결과
아래 이것저것 클릭해봤을 때 로그입니다. (null 은 선택된 아이템이 없는 경우입니다.)
D/ItemAdapter: getSelectedItem = 4
D/ItemAdapter: getSelectedItem = 5
D/ItemAdapter: getSelectedItem = 2
D/ItemAdapter: getSelectedItem = null
D/ItemAdapter: getSelectedItem = 4
D/ItemAdapter: getSelectedItem = null
D/ItemAdapter: getSelectedItem = 3
D/ItemAdapter: getSelectedItem = 4
[Related Post]
[참고자료]
https://eclipse-owl.tistory.com/3
0 comments: