반응형
RecyclerView에 setonClickListener 추가 삭제하기 - RecyclerView 2
전 포스트에서 Recyclerview에 Viewbinding을 적용했는데요, 이번 포스트에서는 뷰 바인딩이 적용된 리사이클러뷰에 버튼을 눌러서 항목을 지우고 삭제하는 기능을 구현해보려 합니다. (뷰바인딩에 익숙하지 않으시다면 아래 링크되어있는 전 포스트를 보고 오시는 것을 추천합니다.)
목표
XML Layout 구성
- activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="추가"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="할일"
android:inputType="textPersonName"
app:layout_constraintEnd_toStartOf="@+id/add_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
- item_todo.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/todoText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="textview"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/delete_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/delete_image"
android:layout_width="20dp"
android:layout_height="23dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_delete_forever_24" />
</androidx.constraintlayout.widget.ConstraintLayout>
RecyclerView 리스트에 EditText String을 추가하는 버튼 구현
- Recyclerview에 리스트를 추가하는 버튼 만들어줍니다.
- MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val data = arrayListOf<Todo>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = TodoAdapter(data)
//추가 시작
add_button.setOnClickListener {
addTask() //addTask함수실행
}
}
fun addTask() {
//editText에서 사용자가쓴 할일을 가져온다.
val todo = Todo(binding.editText.text.toString(),false) //Todo는 데이터 클래스입니다. 요소는 Todo Adapter에서 확인가능합니다.
//가져온 할일을 data arraylist에 추가해줍니다.
data.add(todo)
//아이템이 추가되고 UI가 바뀐걸 업데이트해주는코드
binding.recyclerView.adapter?.notifyDataSetChanged()
}
//추가끝
}
리스트에서 제거하는 버튼
- Recyclerview item에 있는 쓰레기통 모양 버튼을 누르면 recyclerview에서 지워질 수 있도록 합니다.
- Recyclerview item들을 삭제하려면 어느 포지션에 있는 항목이 지워지는지 RecyclerAdapter의 onBindViewHolder에서 가져와야 합니다.
- 받은 position값을 이용해서 onCreate에서 data arrayList에서 item을 제거해야 합니다.
- 아래코드에 코멘트를 번호 순대로 읽으면 이해에 도움됩니다.
- MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val data = arrayListOf<Todo>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//수정시작
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = TodoAdapter(data,
onClickDeleteIcon = { //3. onBindViewHolder에서 listposition을 전달받고 이 함수를 실행하게 된다.
deleteTask(it) //deleteTask함수가 포지션값인 it을 받고 지운다.
}
)
//수정 끝
add_button.setOnClickListener {
addTask()
}
}
fun addTask() {
val todo = Todo(binding.editText.text.toString())
data.add(todo)
binding.recyclerView.adapter?.notifyDataSetChanged()
}
//추가시작
fun deleteTask(todo: Todo) {
data.remove(todo)
binding.recyclerView.adapter?.notifyDataSetChanged()
}
//추가끝
}
- TodoAdapter
data class Todo(
val text: String,
var isDone: Boolean = false,
)
class TodoAdapter(
private val dataSet: List<Todo>,
//추가시작
val onClickDeleteIcon: (todo: Todo) -> Unit //2. delete button이 눌렸을때 onclickDeleteIcon을 실행하라는뜻, 0->Unit이기때문에 함수자체에 return없다는뜻
//추가 끝
) :
RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {
class TodoViewHolder(val binding: ItemTodoBinding) :
RecyclerView.ViewHolder(binding.root) {
val todoText: TextView
get() {
TODO()
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): TodoViewHolder {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.item_todo, viewGroup, false)
return TodoViewHolder(ItemTodoBinding.bind(view))
}
override fun onBindViewHolder(todoViewHolder: TodoViewHolder, position: Int) {//item을 화면에 표시해주는
val listposition = dataSet[position]
todoViewHolder.binding.todoText.text = listposition.text
//추가시작
todoViewHolder.binding.deleteImage.setOnClickListener {
onClickDeleteIcon.invoke(listposition) //1. deleteimage가 눌렸을때 listposition를 전달하면서 onClickDeleteIcon함수를 실행한다.
}
//추가끝
}
override fun getItemCount() = dataSet.size
}
이렇게 하면 리스트가 추가 삭제 기능을 구현하실 수 있습니다. 그런데 화면 회전이나 UI가 변경되는 경우(Activity전환, 앱을 껐다 켜었을 때, fragment가 바뀔 때 etc) 데이터가 모두 사라지게 됩니다. 이 문제를 해결하기 위해 다음 포스트에서는 ViewModel/ LiveData를 활용해서 UI가 변해도 값을 유지하는 기능을 구현해보겠습니다.
반응형