안드로이드 세계

[Android] Recycler View - Step 4 본문

안드로이드(Android)/코틀린(Kotlin)

[Android] Recycler View - Step 4

리안94 2021. 1. 19. 14:44

이번 포스팅에는 개와 고양이 두 종류로 분류하는 작업을 할 것이다.

 

분류하기 위해서 스피너라는 것을 사용할 예정이다.

 

따라서, 추가 다이얼로그에 스피너를 추가해준다.

다이얼로그 프래그먼트. 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/kind"
        android:text="@string/Kind"
        android:textSize="16sp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16sp"
        app:layout_constraintWidth_percent="0.2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>

    <Spinner
        android:id="@+id/kindSelect"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintWidth_percent="0.3"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/kind"/>

    <TextView
        android:id="@+id/name"
        android:text="@string/Name"
        android:textSize="16sp"
        android:layout_marginTop="20sp"
        android:layout_marginStart="16sp"
        app:layout_constraintWidth_percent="0.2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/kind"
        app:layout_constraintLeft_toLeftOf="parent"/>

    <EditText
        android:id="@+id/editName"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:hint="@string/HintName"
        android:layout_marginTop="10sp"
        app:layout_constraintWidth_percent="0.5"
        app:layout_constraintTop_toBottomOf="@id/kind"
        app:layout_constraintLeft_toRightOf="@id/name"
        android:inputType="text" />

    <TextView
        android:id="@+id/phoneNumber"
        android:text="@string/PhoneNum"
        android:textSize="16sp"
        android:layout_marginTop="20sp"
        android:layout_marginStart="16sp"
        app:layout_constraintWidth_percent="0.2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/name"
        app:layout_constraintLeft_toLeftOf="parent"/>

    <EditText
        android:id="@+id/editPhoneNumber"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:hint="@string/HintPhoneNum"
        android:layout_marginTop="10sp"
        app:layout_constraintWidth_percent="0.5"
        app:layout_constraintTop_toBottomOf="@id/name"
        app:layout_constraintLeft_toRightOf="@id/phoneNumber"
        android:inputType="phone"/>

    <Button
        android:id="@+id/cancel"
        android:text="@string/Cancel"
        android:textSize="16sp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintWidth_percent="0.4"
        android:layout_marginTop="30sp"
        android:layout_marginStart="16sp"
        app:layout_constraintTop_toBottomOf="@id/phoneNumber"
        app:layout_constraintLeft_toLeftOf="parent"/>

    <Button
        android:id="@+id/add"
        android:text="@string/Add"
        android:textSize="16sp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="25sp"
        android:layout_marginTop="30sp"
        app:layout_constraintWidth_percent="0.4"
        app:layout_constraintTop_toBottomOf="@id/phoneNumber"
        app:layout_constraintLeft_toRightOf="@id/cancel"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

그리고 다이얼로그 프래그먼트에 스피너 값을 받아올 전역 변수 하나와 스피너 관련 리스너 및 초기화 작업을 해준다.

다이얼로그 프래그먼트

class AnimalDataAddDialogFragment : DialogFragment() {

    private var type = "Cat"
    private lateinit var spinner: Spinner

    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
	...
        setSpinner()
        ...
        
    }
    
    ....

    private fun setSpinner() {
        val spinner = fragmentView?.findViewById<Spinner>(R.id.kindSelect)
        ArrayAdapter.createFromResource(
            requireContext(),
            R.array.AnimalType,
            android.R.layout.simple_spinner_item
        ).also { adapter ->
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
            spinner?.adapter = adapter
        }

        spinner?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onNothingSelected(parent: AdapterView<*>?) {

            }

            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                type = spinner?.selectedItem.toString()
            }
        }
    }


}

추가해줘야 하는 부분만 작성한 내용이다.

 

아이템을 클릭할 때 type이라는 변수의 값을 변경해주는 간단한 내용이다.

 

스피너에 사용할 array는 res -> values에 arrays.xml을 만들고 아래와 같이 추가해준다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="AnimalType">
        <item>Cat</item>
        <item>Dog</item>
    </string-array>
</resources>

 

마지막으로는 어뎁터를 수정해주면 된다.

 

두 가지 타입이 존재하기 때문에 getItemViewType를 오버라이드 해준다.

override fun getItemViewType(position: Int): Int {
        val type = animalsData[position].type

        return if (type == "Cat")
            0
        else
            1
    }

getItemViewType의 값이 0이라면 Cat, 아니라면 Dog인 경우가 된다.

 

뷰 홀더를 하나 더 구성해준다.

inner class DogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(animalsData: Animal) {
            itemView.findViewById<ImageView>(R.id.type).setImageResource(R.mipmap.dog)
            itemView.findViewById<TextView>(R.id.animalName).text = animalsData.name
            itemView.findViewById<TextView>(R.id.phoneNumber).text = animalsData.phoneNumber

            itemView.findViewById<ConstraintLayout>(R.id.parentView).setOnClickListener {
                listener.onItemClick(it, adapterPosition)
            }

            itemView.findViewById<ConstraintLayout>(R.id.parentView).setOnLongClickListener {
                listener.onItemLongClick(it, adapterPosition)
                true
            }
        }
    }

 

 

다음은 onCreateViewHolder를 다음과 같이 수정한다.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        // Connect Xml
        // Cat: viewType = 0
        // Dog: viewType = 1
        return if (viewType == 0) {
            val view =
                LayoutInflater.from(parent.context).inflate(R.layout.catlistdata, parent, false)
            CatViewHolder(view)
        } else {
            val view =
                LayoutInflater.from(parent.context).inflate(R.layout.doglistdata, parent, false)
            DogViewHolder(view)
        }
    }

 

onBindViewHolder도 동일하게 수정해준다.

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        //BindViewHolder
        if (getItemViewType(position) == 0) {
            if(holder is CatViewHolder)
                holder.bind(animalsData = animalsData[position])
        } else {
            if (holder is DogViewHolder)
                holder.bind(animalsData = animalsData[position])
        }
    }

 

사용할 준비는 모두 끝이 났다.

 

결과는 다음과 같다.

 

고양이 타입이 선택된 경우는 고양이 사진이 나오게 되고, 개 타입을 선택한 경우 개의 사진이 나오게 된다.

 

이번 포스팅은 단순 예제이기 때문에 이렇게 사용을 하였지만, 레이아웃 형식이 동일하기 때문에 뷰 홀더 내에서 분기 처리해서 처리해도 되는 문제였다.

 

뷰타 입을 나눠서 작성하게 되는 경우는 대체로 하나의 리사이클 러뷰에 포함되지만 레이아웃 형식이 다른 경우 뷰타 입으로 나눠서 작업하면 좋다.

 

아래의 깃 주소는 해당 내용을 가지고 포스팅의 내용만 가지고 작성한 경우, DataBinding을 사용한 경우, DataBinding + MVVM, DataBinding + MVVM + ListAdapter를 사용한 방식을 설명해두었으니 참고해서 보아도 된다.(피드백은 언제나 환영입니다.)

github.com/pyg1007/RecyclerView-Sample

 

pyg1007/RecyclerView-Sample

Contribute to pyg1007/RecyclerView-Sample development by creating an account on GitHub.

github.com

 

Comments