[Android/Kotlin 06-2] 당근마켓 클론코딩 사과마켓(최종)

이다을·2023년 8월 25일
1

지난번에 이어 추가로 2가지 기능을 더 구현했다.

🔗 사과마켓 github
🔗 사과마켓 1탄

느므나도 귀여운 사과마켓(🍎) 최종

  • (✔) RecyclerViewer를 이용해 리스트 화면을 만들어준다.
  • (✔) 상품 이미지는 모서리를 라운드 처리한다.
  • (✔) 이름은 최대 두 줄이고, 넘어가는 부분은 ...으로 처리한다.
  • (✔) 뒤로가기(BACK)버튼 클릭시 다이얼로그 창을 띄운다.
  • (✔) Spinner로 동이름을 변경한다.
  • (✔) 상단 종모양 아이콘을 누르면 Notification을 생성한다.
  • (✔) 상품 가격은 1000단위로 콤마(,) 처리한다.
  • (✔) 아이템들 사이에 회색 라인으로 구분해준다.
  • (✔) 플로팅 버튼을 클릭하면 스크롤 최상단으로 이동한다.
  • (✔) 상품 선택시 해당 상품의 상세 페이지로 이동한다.
  • (✔)아이템을 롱클릭하면 다이얼로그를 띄워 상품을 삭제할 수 있도록 한다.
  • (✔) 상품 상세페이지 이동시 intent로 객체를 전달한다.(Parcelize)
  • (✔) 메인에서 전달받은 데이터를 상품 상세페이지에 표시한다.
  • (✔) 상세페이지에서 하단 가격을 제외하고 전체화면을 스크롤되게한다.
  • 상품 상세 화면에서 좋아요 선택시 아이콘 변경 및 Snackbar 메세지를 표시한다.(+좋아요 카운트, 해제시 이전 상태로 되돌림)
  • (✔)상단 뒤로가기(<)버튼을 누르면 상세 화면은 종료되고 메인화면으로 돌아간다.

⚡롱클릭시 다이얼로그창 띄우기, 아이템 삭제

선풍기를 없애볼게여 얍!
선풍기 아이템을 길게 누르면 정말로 삭제 하겠냐는 다이얼로그 창이뜹니다. 확인을 누르면 선풍기 항목이 사라진것을 볼 수 있습니다.

⚡LongItemClick 인터페이스

LongItemClick 인터페이스는 롱클릭 이벤트를 처리하기 위한 콜백을 정의합니다.
onLongClick(view: View, position: Int) 메서드는 롱클릭한 아이템의 View와 해당 아이템의 위치(position)을 전달받습니다.

interface LongItemClick {
        fun onLongClick(view : View, position : Int)
    }
    var longItemClick : LongItemClick? = null
    

⚡removeItem(position: Int) 함수

position이 유효한 범위 내에 있는 경우에만 아이템을 삭제하고 어댑터에게 변경 사항을 알립니다.

fun removeItem(position: Int) {
    if (position in 0 until mItems.size) {
        mItems.removeAt(position)
        notifyItemRemoved(position)
    }
}

⚡롱클릭 이벤트 처리

아이템 롱클릭 이벤트가 발생하면 AlertDialog가 생성됩니다. 확인 버튼을 누르면 removeItem(position) 함수가 호출되어 해당 아이템을 삭제하고 어댑터에게 변경 사항을 알립니다.

adapter.longItemClick = object : MyAdapter.LongItemClick {
    override fun onLongClick(view: View, position: Int) {
        val alertDialog = AlertDialog.Builder(this@MainActivity)
            .setIcon(R.drawable.chat)
            .setTitle("삭제")
            .setMessage("정말로 삭제하시겠습니까?")
            .setPositiveButton("확인") { dialog, which ->
                adapter.removeItem(position)
            }
            .setNegativeButton("취소", null)
            .create()
        alertDialog.show()
    }
}

⚡상단 뒤로가기 버튼

뒤로가기 버튼 클릭시 메인 엑티비티로 전환되며, 상세페이지는 종료된다.

val backButton = findViewById<ImageButton>(R.id.backButton)
backButton.setOnClickListener {
    val intent = Intent(this, MainActivity::class.java)
    startActivity(intent)
    finish()
}

⚡RecyclerView ItemDecoration

원래 하단 영역의 선들을 xml의 view로 만들어 줬었는데요, 리사이클러뷰의 아이템 데코레이션으로 변경 해주었습니다.

  • 데코레이션을 사용하면 아이템 index별로 간격을 조절할 수 있습니다. 그러면 0번째 아이템과 마지막 아이템간의 미묘한 간격 차이를 해결할 수 있습니다.
  • xml에서 뷰를 그리면 새로운 아이템을 그릴때마다 메모리를 차지하기 때문에 성능에 대한 문제점이 발생할 수 있습니다. 리사이클러뷰 리스트를 불러올 땐 단순히 낱개의 아이템을 불러오는 것이 아닌 대량의 아이템을 불러오기 때문입니다.
class AddressAdapterDecoration : RecyclerView.ItemDecoration() {
    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)

        val paint = Paint()
        paint.color = Color.GRAY

        for (i in 0 until parent.childCount) {
            val child = parent.getChildAt(i)
            val layoutParams = child.layoutParams as RecyclerView.LayoutParams
            val top = (child.bottom + layoutParams.bottomMargin + 10).toFloat()
            val bottom = top + 1f

            val left = parent.paddingStart.toFloat()
            val right = (parent.width - parent.paddingEnd).toFloat()

            c.drawRect(left, top, right, bottom, paint)
        }
    }
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        val offset = 10
        outRect.top = offset
        outRect.bottom = offset
    }
}

⚡onDraw() 함수

onDraw() 함수는 아이템 구분선을 그리는 역할을 합니다. 각 아이템의 하단에 10dp의 추가 간격을 주고, 그 아래에 1dp의 높이로 구분선을 그립니다.

⚡getItemOffsets() 함수

getItemOffsets() 함수는 아이템 간격을 설정하는 역할을 합니다. 각 아이템의 위쪽과 아래쪽에 모두 10dp의 간격을 설정합니다. 매게변수로 아이템 테두리, 데코레이트할 자식 뷰, 해당 데코레이션 클래스를 추가한 리사이클러뷰, 현재 리사이클러뷰의 상태가 있습니다.

  • position 변수를 구하기 위해 parent(리사이클러뷰)의 어뎁터 안에 들어있는 자식(view)들의 위치값을 가져옵니다.
  • count는 리사이클러뷰의 total item count를 불러옵니다.
  • onDraw() 에는 Canvas객체가 있습니다. 뷰를 그릴때 반드시 필요합니다.
  • Paint 객체를 생성해서 간단하게 색상을 지정하고 긴 직사각형을 그리기 위해 상,하,좌,우 변수를 모두 구합니다.

profile
나도 개발 할래

0개의 댓글