리사이클러뷰 다중 선택, 삭제

Hwan·2023년 3월 23일
0

GiftMap

목록 보기
9/15

구현할 내용

1. ManageActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_manage)

        addbtn = findViewById(R.id.button1)
        editbtn = findViewById(R.id.button2)
        ...

        editbtn.setOnClickListener{
            toggleMultiSelect()
        }

        ...
    }

ㄴ 편집 버튼 클릭시 OnClinckLinstener 실행하여 버튼의 text를 변경하고, imageAdapter를 실행

private fun toggleMultiSelect() {
        isMultiSelect = !isMultiSelect
        if (isMultiSelect) {
            addbtn.text = "취소"
            editbtn.text = "삭제"
        } else {
            addbtn.text = "추가"
            editbtn.text = "편집"
        }
        imageAdapter.toggleMultiSelect()
    }

ㄴ 이때, 어댑터는 private lateinit var imageAdapter: ImageAdapter로 초기화 되어 있어야 한다.

2. ImageAdapter.kt

class ImageAdapter(private val items: ArrayList<String>) : RecyclerView.Adapter<ImageAdapter.ViewHolder>() {

    private var isMultiSelect = false
    private val selectedItems = mutableListOf<String>()

    fun toggleMultiSelect() {
        isMultiSelect = !isMultiSelect
        if (isMultiSelect) {
            notifyDataSetChanged()
            selectedItems.clear()
        } else {
            deleteSelectedItems()
        }
    }
    // 아래에 이어서

ㄴ toggleMultiSelect가 전환됨에 따라 선택되는 item의 배경색을 바꿔주기 위해 위와 같은 함수를 작성

private fun deleteSelectedItems() {
        val storageRef = FirebaseStorage.getInstance().reference
        val databaseRef = Firebase.database.getReference("ocr_results")

        // 선택된 이미지들에 대해 firebase storage와 DB에서 삭제
        selectedItems.forEach { imageUrl ->
            // 파일 경로에서 파일 이름만 추출
            val filename = imageUrl.substringAfterLast("%2F")
                .substringBeforeLast("?")
            Log.d("ImageAdapter", filename)

            // firebase storage에서 해당 이미지 삭제
            storageRef.child("images/$filename").delete()

            // firebase DB에서 해당 이미지 OCR 결과 삭제
            databaseRef.orderByChild("image_url").equalTo("/images/$filename").addListenerForSingleValueEvent(object :
                ValueEventListener {
                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    for (snapshot in dataSnapshot.children) {
                        snapshot.ref.removeValue()
                    }
                }

                override fun onCancelled(databaseError: DatabaseError) {
                    Log.d("ImageAdapter", "onCancelled: ${databaseError.toException()}")
                }
            })
        }

        // 선택된 아이템 초기화
        selectedItems.clear()
        isMultiSelect = false

        // 어댑터 갱신
        notifyDataSetChanged()
    }
    
    // 아래에 이어서

ㄴ 파일명을 이용하여 storage와 DB에서 데이터를 삭제. 이때 파일 이름이 잘못 지정되는 오류를 반복적으로 겪어 val filename = imageUrl.substringAfterLast("%2F").substringBeforeLast("?")를 이용하여 필요한 부분만 잘라내는 작업을 하였다.

	class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val imageView: ImageView = itemView.findViewById(R.id.img)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.giftlist, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return items.size
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val imageUrl = items[position]
        Glide.with(holder.imageView.context).load(imageUrl).into(holder.imageView)

        if (isMultiSelect) {
            val isSelected = selectedItems.contains(imageUrl)
            holder.itemView.setBackgroundColor(
                if (isSelected) {
                    ContextCompat.getColor(holder.itemView.context, R.color.selectpink)
                } else {
                    Color.TRANSPARENT
                }
            )

            holder.itemView.setOnClickListener {
                if (isSelected) {
                    selectedItems.remove(imageUrl)
                } else {
                    selectedItems.add(imageUrl)
                }
                notifyItemChanged(position)
            }
        } else {
            holder.itemView.setBackgroundColor(Color.TRANSPARENT)
            holder.itemView.setOnClickListener(null)
        }
    }
}

ㄴ 그밖에 필요한 부분을 마저 작성한다. ViewHolder를 이용하여 리사이클러뷰를 보이고, Glide 라이브러리를 사용하여 이미지를 불러온다.

다중선택 기능이 활성화된 상태라면 select된 item을 따로 selectedItems 이라는 리스트에 보관해야 앞서 작성한 코드들이 정상적으로 작동할 수 있다.

0개의 댓글