본문 바로가기
개발노트/Kotlin

9주차 4일 뷰 타입 분기 구현 완, 북마크 구현 완

by 시계속세상은아직돌아가는중 2023. 9. 7.

1. 뷰 타입

 

    companion object {
        const val VIEW_TYPE_1 = 1
        const val VIEW_TYPE_2 = 2
        const val VIEW_TYPE_3 = 3
    }

    private var list = mutableListOf<UserModel>()
    private var viewTypeState = VIEW_TYPE_1
   fun typeChange(newType: Int) {

        viewTypeState = newType

        notifyDataSetChanged()
    }

어뎁터 추가문구

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            VIEW_TYPE_1 -> {
                ContactViewHolder(
                    ContactItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                )
            }

            VIEW_TYPE_2 -> {
                Type2ViewHolder(
                    ContactItem2Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                )
            }

            else -> {
                Type3ViewHolder(
                    ContactItem3Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                )
            }
        }
    }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = list[position]
        when (viewTypeState) {
            VIEW_TYPE_1 -> {
                (holder as ContactViewHolder).onBind(item)

                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }

            VIEW_TYPE_2 -> {
                (holder as Type2ViewHolder).onBind(item)
                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }

            VIEW_TYPE_3 -> {
                (holder as Type3ViewHolder).onBind((item))
                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }
        }


    }

액티비티

interface ViewTypeChangeLisener{
    fun onViewTypeChanged(type:Int)
}
        mainFabViewTypeChange.setOnClickListener {
            if (viewTypeState == ContactAdapter.VIEW_TYPE_1) {
                mainFabViewTypeChange.foreground =
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_pikachu)

                viewTypeState = ContactAdapter.VIEW_TYPE_2
                lisener?.onViewTypeChanged(viewTypeState)

            } else if(viewTypeState == ContactAdapter.VIEW_TYPE_2) {
                mainFabViewTypeChange.foreground =
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_evee)

                viewTypeState = ContactAdapter.VIEW_TYPE_3
                lisener?.onViewTypeChanged(viewTypeState)

            } else {
                mainFabViewTypeChange.foreground =
                    ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_ditto)
                viewTypeState = ContactAdapter.VIEW_TYPE_1
                lisener?.onViewTypeChanged(viewTypeState)
            }
        }

 

흐름은 이러하다

 

메인 액티비티에서 정의된 typestate를 인터페이스에 실어 날라서 fragment에서 받고

정의된 인터페이스에서 adapter에서 정의된 메소드를 이용하여 state를 조절해준다.

 

뷰 타입의 변화가 일어나는 부분에서 레이아웃 매니저를 통해 그리드/리니어 형태를 정의해준다.

그리드 타입 제어 시 

GridLayoutManager(requireContext(), 2)

이 부분을 통해 2개의 아이템씩 정의할 수 있다.

 

프래그먼트

    override fun onViewTypeChanged(type: Int) {
        contactAdapter.typeChange(type)

        if (type == ContactAdapter.VIEW_TYPE_3) {
            contactRecycerview.layoutManager = GridLayoutManager(requireContext(), 2)
            Log.d("타입", contactAdapter.getViewTypeState().toString())
        } else {
            contactRecycerview.layoutManager = LinearLayoutManager(requireContext())
        }
    }

 

 

2. 북 마크

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".contact.ContactFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/contact_recycerview_bookmark"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/contact_recycerview"
        />

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#8C8C8C"
        android:elevation="0dp"
        app:layout_constraintTop_toBottomOf="@+id/contact_recycerview_bookmark"
        app:layout_constraintBottom_toTopOf="@id/contact_recycerview"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/contact_recycerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintTop_toBottomOf="@+id/contact_recycerview_bookmark"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

두 개의 리사이클리어뷰로 북마크/기본 아이템의 리사이클리어뷰를 만들고

북마크 프래그먼트의 어뎁터를 만든 뒤 그려준다.

 

북 마크 프래그 먼트에서 사용되는 메소드

 

    fun setItem(item: UserModel) {
        if (item == null) return
        if (!item.isBookMark) {
            bookMarkList.add(item)
            notifyDataSetChanged()
        }
    }

    fun removeItem(item: UserModel) {
        if (item == null) return

        val removeItem = bookMarkList.find { it == item }

        bookMarkList.remove(removeItem)

        notifyDataSetChanged()

    }

    fun removePositionItem(position: Int) {
        if (position == null) return

        bookMarkList.removeAt(position)

        notifyDataSetChanged()

    }

    fun getItemPosition(position: Int):UserModel{
        return bookMarkList[position]
    }

컨택트 어뎁터에서 사용되는 메소드

    fun getViewTypeState(): Int {
        return viewTypeState
    }

    fun typeChange(newType: Int) {

        viewTypeState = newType

        notifyDataSetChanged()
    }

    fun getItemPosition(position: Int):UserModel{
        return list[position]
    }

    fun setBookMark(isBookMark : Boolean,position: Int){
        list[position].isBookMark = isBookMark
        notifyDataSetChanged()
    }

프래그먼트에서 제어해주는 인터페이스

      contactAdapter.itemLongClick = object : ContactAdapter.ItemLongClick {
            override fun onLongClick(view: View, position: Int) {
                val item = contactAdapter.getItemPosition(position)
                if (!item.isBookMark) {
                    //북마크 추가
                    bookMarkAdapter.setItem(item)
                    item.isBookMark = true
                    contactAdapter.setBookMark(item.isBookMark,position)
                }else{
                    //북마크 해제
                    bookMarkAdapter.removeItem(item)
                    item.isBookMark = false
                    contactAdapter.setBookMark(item.isBookMark,position)
                }
            }

        }
        contactRecycerviewBookmark.adapter = bookMarkAdapter

        bookMarkAdapter.onItemLongClick = object :BookMarkAdapter.ItemLongClick{
            override fun onLongClick(view: View, position: Int) {
                val item = bookMarkAdapter.getItemPosition(position)
                bookMarkAdapter.removePositionItem(position)
                item.isBookMark = false
                contactAdapter.setBookMark(item.isBookMark,position)
            }

        }

이 흐름을 통해 롱 클릭 시 북마크가 온/오프가 되며

       val item = list[position]
        when (viewTypeState) {
            VIEW_TYPE_1 -> {
                (holder as ContactViewHolder).onBind(item)

                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }

            VIEW_TYPE_2 -> {
                (holder as Type2ViewHolder).onBind(item)
                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }

            VIEW_TYPE_3 -> {
                (holder as Type3ViewHolder).onBind((item))
                holder.itemView.setOnLongClickListener(){
                    itemLongClick?.onLongClick(it,position)
                    true
                }
            }
        }

인터페이스로 구현되었기 때문에 각각의 홀더에만 들어가면 된다.

 

3. xml의 이상한 오류

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:background="?attr/selectableItemBackground"
    tools:ignore="contentDescription">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/contact_book_mark_behind"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#40C057"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/contact_book_mark_iv_call"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginStart="30dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_call" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/contactbook_mark__swipe"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:foreground="?attr/selectableItemBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/contact_book_mark_iv_bookmark"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginEnd="30dp"
            android:src="@drawable/ic_book_mark_ball_on"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/contact_book_mark_iv_profile"
            android:layout_width="80dp"
            android:layout_height="89dp"
            android:layout_marginStart="4dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_launcher_foreground" />

        <TextView
            android:id="@+id/contact_book_mark_tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="35dp"
            android:text=""
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/contact_book_mark_iv_profile"
            app:layout_constraintTop_toTopOf="parent" />

        <View
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:elevation="4dp"
            app:layout_constraintBottom_toBottomOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

여기서 view부분이 삭제되면 해당 xml자체거 어그러지는 이상한 오류가 발생했다.

이에 대한 원인규명중이기는 하나 이유는 모르겠다

'개발노트 > Kotlin' 카테고리의 다른 글

9주차를 돌아보며  (0) 2023.09.11
9주차 5일  (0) 2023.09.08
8주차를 돌아보며  (0) 2023.09.04
9주차 1일 팀프로젝트-xml과 drawableResource 그리고 color  (0) 2023.09.04
8주차 5일 fragment와 액티비티등  (0) 2023.09.01