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로 구현