728x90

5일 차 swipe-to-action  오른쪽으로 밀었을 때 아이템 삭제 기능 추가

ContactListAdapter 

const val TYPE_HEADER = 0
const val TYPE_CONTENT_LIST = 1
const val TYPE_CONTENT_GRID = 2


class ContactListAdapter(private val layoutManager: GridLayoutManager) :
    ListAdapter<ContactItems, RecyclerView.ViewHolder>(diffUtil) {
    var itemClick: ItemClick? = null
    var favoriteClick: FavoriteClick? = null

    companion object {
        val diffUtil = object : DiffUtil.ItemCallback<ContactItems>() {
            override fun areItemsTheSame(oldItem: ContactItems, newItem: ContactItems): Boolean {
                return oldItem.ItemID == newItem.ItemID
            }

            override fun areContentsTheSame(oldItem: ContactItems, newItem: ContactItems): Boolean {
                return oldItem == newItem
            }
        }
    }

    interface ItemClick {
        fun onClick(item: ContactItems)
    }

    interface FavoriteClick {
        fun onFavoriteClick(item: ContactItems, position: Int)
    }

    override fun getItemViewType(position: Int): Int {
        val item = getItem(position)
        val span = layoutManager.spanCount

        if (item is ContactItems.Header) {
            return TYPE_HEADER
        }

        if (item is ContactItems.Contents && span == 1) {
            return TYPE_CONTENT_LIST
        }

        if (item is ContactItems.Contents && span > 1) {
            return TYPE_CONTENT_GRID
        }
        throw IllegalArgumentException("Invaild span count")
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)

        if (viewType == TYPE_HEADER) {
            return HeaderViewHolder(ItemHeaderRecyclerViewBinding.inflate(inflater, parent, false))
        }

        if (viewType == TYPE_CONTENT_LIST) {
            return ContentsViewHolder(
                ItemContactRecyclerViewBinding.inflate(
                    inflater,
                    parent,
                    false
                )
            )
        }

        if (viewType == TYPE_CONTENT_GRID) {
            return ContentGridItemViewHolder(
                ItemContactRecyclerViewGridBinding.inflate(
                    inflater,
                    parent,
                    false
                )
            )
        }
        throw IllegalArgumentException("Invalid view type")
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = getItem(position)

        if (item is ContactItems.Header) {
            with(holder as HeaderViewHolder) {
                location.text = item.location
            }
        }

        if (item is ContactItems.Contents) {
            with(holder as ContactItemViewHolder) {
                name.text = item.itemName
                ivThumbnail.setThumbnailImage(item.thumbnailImage)
                favoriteIcon.checkFavorite(item)
                itemView.setOnClickListener { itemClick?.onClick(item) }
                favoriteButton.setOnClickListener { favoriteClick?.onFavoriteClick(item, position) }
            }
        }
    }

    private fun ImageView.setThumbnailImage(image: Int?) {
        load(image ?: R.drawable.main_symbol)
    }

    private fun ImageView.checkFavorite(item: ContactItems.Contents) {
        load(if (item.favorite) R.drawable.favorite_big_on else R.drawable.favorite_big_off)
    }

    fun getPosition(position: Int): ContactItems {
        return ContactItemManager.sortAllWithHeader()[position]
    }
}

 

SwipeHelperCallback

class SwipeHelperCallback(
    private val context: Context,
    private var adapter: ContactListAdapter,
    private val recyclerView: RecyclerView
) :
    ItemTouchHelper.Callback() {
    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        if (viewHolder.itemViewType == TYPE_HEADER) {
            return makeMovementFlags(0, 0)
        }
        return makeMovementFlags(0, LEFT or RIGHT)
    }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val position = viewHolder.adapterPosition
        val item = adapter.getPosition(position) as ContactItems.Contents

        //오른쪽 스와이프 시 전화연결 //왼쪽 스와이프 시 아이템 삭제
        if (direction == ItemTouchHelper.RIGHT) callConnect(item) else removeContact(item)
        adapter.notifyDataSetChanged()
    }
	//스와이프 속도 
    override fun getSwipeEscapeVelocity(defaultValue: Float): Float {
        return defaultValue * 20
    }

    private fun callConnect(item: ContactItems.Contents) {
        item.let {
            val phoneNumber = it.phoneNumber
            Intent(Intent.ACTION_DIAL).apply {
                data = Uri.parse("tel:$phoneNumber")
                context.startActivity(this)
            }
        }
    }

    private fun removeContact(item: ContactItems.Contents) {
        val logoImage = ImageView(context).apply {
            scaleType = ImageView.ScaleType.CENTER_CROP
            val width = LayoutParams.MATCH_PARENT
            val height = 500
            layoutParams = LinearLayout.LayoutParams(width, height).apply {
                topMargin = 100
            }
            adjustViewBounds = true
            item.thumbnailImage?.let { setImageResource(it) }

        }
        val contactText = TextView(context).apply {
            textSize = 30f
            gravity = Gravity.CENTER
            item.phoneNumber.let { text = it }
        }
        val messageText = TextView(context).apply {
            textSize = 20f
            gravity = Gravity.CENTER
            layoutParams =
                LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
                    .apply {
                        topMargin = 100
                        bottomMargin = 50
                    }
            text = "연락처를 삭제 하시겠습니까?"
        }
        val layout = LinearLayout(context).apply {
            orientation = LinearLayout.VERTICAL
            addView(logoImage)
            addView(contactText)
            addView(messageText)
        }

        AlertDialog.Builder(context).apply {
            setView(layout)
            setPositiveButton("확인") { _, _ ->
                item.let {
                    ContactItemManager.contactItems.remove(item)
                    adapter.submitList(ContactItemManager.sortAllWithHeader())
                }
            }
            setNegativeButton("취소") { _, _ ->
                adapter.notifyDataSetChanged()
            }
            show()
        }
    }
}

 

해당 adapter 에 notify를 해줘야되는데 계속 notifyData~만 사용해서 갱신이 안됐었음 너무 오랜시간 삽질함 

팀 프로젝트를 하면서 가장 어려운건 역시 남이 짠 코드를 보면서 이어서 코드를 작성 할 때 어려움이 있음

내가 실력이 많이 부족한 것을 느낌 

 

 

//아이템 삭제시 dialog는 시간관계상 AlertDialog로 구현 

+ Recent posts