안녕하세요. 이어서 이번에는 연락처를 삭제하는 기능을 구현해보려고 합니다.
연락처의 권한 획득과 연락처를 불러오기 위한 글은 아래의 게시글을 확인해주세요.
연락처 추가 및 수정 게시글은 아래에서 확인해주세요.
지난 게시글들과 이어서 진행되기 때문에 앞선 게시글들을 보고 와주세요.
이제 연락처 삭제 방법에 대해 알아보겠습니다.
view_contacts_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout ... >
<LinearLayout ... >
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:clickable="false"
android:minWidth="0dp"
android:minHeight="0dp" />
<TextView ... />
<TextView ... />
</LinearLayout>
<View ... />
</androidx.constraintlayout.widget.ConstraintLayout>
연락처 목록의 디자인인 view_contacts_list.xml에 삭제를 하기 위한 CheckBox를 추가해 줍니다.
ContactsAdapter.kt
class ContactsAdapter(private val contactsList: ArrayList<ContactsData>, private val onItemClickListener: OnItemClickListener, private val checkedList: MutableSet<Int>) : RecyclerView.Adapter<ContactsAdapter.ViewHolder>() {
interface OnItemClickListener {
fun onItemClickListener(position: Int)
fun onItemLongClickListener(position: Int)
}
private var isDeleteMode = false
private var longPosition = -1
...
fun setDeleteMode(deleteMode: Boolean) {
isDeleteMode = deleteMode
notifyItemRangeChanged(0, itemCount)
}
inner class ViewHolder(private val binding: ViewContactsListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind() {
binding.txtName.text = contactsList[adapterPosition].name
binding.txtPhoneNumber.text = PhoneNumberUtils.formatNumber(contactsList[adapterPosition].number, Locale.getDefault().country)
binding.checkbox.isVisible = isDeleteMode
if (isDeleteMode) {
binding.checkbox.isChecked = checkedList.any { adapterPosition == it }
} else {
checkedList.clear()
binding.checkbox.isChecked = false
longPosition = -1
}
if (longPosition == adapterPosition) {
binding.checkbox.isChecked = true
checkedList.add(adapterPosition)
}
itemView.setOnClickListener {
binding.checkbox.performClick()
if (binding.checkbox.isChecked) {
checkedList.add(adapterPosition)
} else {
checkedList.remove(adapterPosition)
}
}
itemView.setOnLongClickListener {
checkedList.add(adapterPosition)
onItemClickListener.onItemLongClickListener(adapterPosition)
return@setOnLongClickListener false
}
}
}
}
isDeleteMode, longPosition : isDeleteMode와 longPosition 전역 변수를 생성합니다. 이 변수들은 삭제 모드인지 확인하는 Boolean값과 롱 클릭 시 클릭된 연락처는 체크를 할 수 있도록 하기 위한 변수입니다.
OnItemClickListener : 기존에 만들어 놨던 OnItemClickListener Interface에 onItemLongClickListener를 추가해줍니다. itemView가 롱 클릭됐을 경우 이 메서드로 callback을 전달하게 됩니다.
setDeleteMode() : 이 메서드는 MainActivity에서 삭제모드를 설정/해제할 때 사용되는 메서드입니다.
binding.checkbox.isVisible = isDeleteMode : 삭제 모드일 경우 체크박스를 visible 처리하고 삭제 모드가 아닐 경우라면 gone처리를 해주게 됩니다.
if ~ else : 삭제 모드일 때는 checkedList에 포지션이 속할 경우 checkBox를 checked 해주게 됩니다. 삭제 모드가 아닐 경우에는 checkedList를 clear 해주고 checkBox의 checked를 해제해 줍니다.
setOnClickListener : 기존에는 클릭했을 경우 interface callback만 실행시켰었는데 삭제 모드일 경우에 checkBox를 체크해주고 checkedList에 checked라면 add 아니라면 remove 해주며, 삭제 모드가 아닐 경우에만 callback을 전달합니다.
setOnLongClickListener : itemView를 롱 클릭했을 경우 해당 아이템을 checkedList에 추가해주고, interface callback을 전달합니다.
MainActivity.kt
class MainActivity : AppCompatActivity(), View.OnClickListener {
...
private var checkedList: MutableSet<Int> = mutableSetOf()
private var isDeleteMode = false
private val onItemClickListener = object : ContactsAdapter.OnItemClickListener {
...
override fun onItemLongClickListener(position: Int) {
isDeleteMode = true
setModeUI()
}
}
...
override fun onClick(v: View?) {
when (v) {
...
binding.includeTitle.btnDelete -> {
checkedList.sortedDescending().forEach {
setDeleteContacts(contactsList[it], it)
}
Toast.makeText(this, "연락처 삭제가 완료되었습니다.", Toast.LENGTH_SHORT).show()
isDeleteMode = false
setModeUI()
}
}
}
override fun onBackPressed() {
if (isDeleteMode) {
isDeleteMode = false
setModeUI()
} else {
super.onBackPressed()
}
}
...
private fun initListener() {
...
binding.includeTitle.btnDelete.setOnClickListener(this)
}
private fun setModeUI() {
binding.includeTitle.btnDelete.isVisible = isDeleteMode
binding.btnAddContacts.isVisible = !isDeleteMode
contactsAdapter?.setDeleteMode(isDeleteMode)
}
private fun setDeleteContacts(contacts: ContactsData, index: Int) {
contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, "${ContactsContract.RawContacts.CONTACT_ID}=?", arrayOf(contacts.contactsId.toString()))
contactsList.removeAt(index)
contactsAdapter?.notifyItemRemoved(index)
}
}
checkedList, isDeleteMode : checkedList는 check 된 Item의 position을 저장하고, isDeleteMode는 Adapter와 동일하게 삭제 모드를 뜻합니다.
onClick() : onClickListener에 TitleBar의 btnDelete를 추가해줍니다. TitleBar의 btnDelete를 클릭할 경우 checkedList의 아이템들을 setDeleteContact로 넘겨 연락처를 삭제하고 삭제가 완료되면 삭제 모드를 해제합니다.
onBackPressed() : 삭제 모드일 때 사용자가 back버튼 동작을 하였을 때 삭제 모드를 해제하고 삭제 모드가 아니라면 onBackPressd 동작을 하게 됩니다.
initListener() : 이 메서드에서 TitleBar의 btnDelete의 리스너를 등록합니다.
setModeUI() : 삭제 모드라면 타이틀바의 삭제버튼을 visible처리해주고, btnAddContacts버튼을 gone처리, 아까 생성했던 contactsAdapter의 setDeleteMode에 삭제모드 여부를 전달합니다.
setDeleteContacts() : 이 메서드는 연락처를 실제로 삭제하는 부분의 메서드입니다. ContactsData에 저장되어있던 연락처의 ID를 이용하여 이 ID를 contentResolver.delete에 전달하여 삭제합니다. 삭제된 연락처는 contactsList에서 삭제하고 RecyclerView의 해당 Position에 Remove 했다고 알려줍니다.
그럼 지금까지 만든 내용의 결과를 보겠습니다.
이번에는 연락처의 삭제하는 방법에 대해 알아보았습니다.
연락처의 소스코드는 아래의 제 Github에서 보실 수 있습니다.
문제가 있거나 이해가 되지 않는 부분이 있으시면 댓글을 남겨주시면 답변드리겠습니다!
'Android > Libraries' 카테고리의 다른 글
[Android] 안드로이드 Permission(권한) 예제 - 연락처/주소록 만들기 (연락처 추가/수정) (0) | 2022.08.07 |
---|---|
[Android] 안드로이드 Permission(권한) 예제 - 연락처/주소록 만들기 (권한 획득, 연락처 불러오기) (0) | 2022.07.24 |
[Android] Parcelable 생성 Parcelize로 편하게 생성하기(with Serializable) (0) | 2022.07.24 |
[Android] 안드로이드 Permission(권한) 종류 및 권한 획득 예제(지문인증 / 생체 인증) (0) | 2022.07.11 |
[Android] 안드로이드12 대응 SplashScreen(스플래시 스크린) 만들기 (1) | 2022.07.09 |