Android Kotlin RecyclerView Header/Footer - 리사이클러뷰(상하단 레이아웃)

Notepad96

·

2021. 10. 25. 18:37

300x250

 

 

 


1. 결과

 

 

 

 


2. Layout


2-1. activity_main.xml (메인 레이아웃)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

 

2-2. list_header.xml (리스트 헤더 레이아웃)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:text="Title"
            android:textSize="22sp"
            android:textStyle="bold"
            android:textColor="@color/black"
            android:layout_marginLeft="40dp"/>

        <LinearLayout
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="Content"
            android:textSize="22sp"
            android:textStyle="bold"
            android:textColor="@color/black"/>
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#333333"/>

</LinearLayout>

 

# RecyclerView에서 Header로 사용할 Layout

 

 

2-3. list_item.xml (리스트 아이템 레이아웃)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/layoutItem"
    android:orientation="vertical">

    <TextView
        android:id="@+id/layoutEmpty"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:layout_weight="1"
        android:gravity="center"
        android:visibility="gone"
        android:text="리스트가 비었습니다."
        android:textSize="22sp"
        android:textColor="@color/black"/>

    <LinearLayout
        android:id="@+id/layoutNotEmpty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <CheckBox
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="0dp"/>

        <TextView
            android:id="@+id/textListTitle"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:text="Test Title 1"
            android:textSize="18sp"
            android:textColor="@color/black"
            android:gravity="center_vertical"/>

        <LinearLayout
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

        <TextView
            android:id="@+id/textListContent"
            android:layout_width="wrap_content"
            android:layout_weight="1"
            android:layout_height="match_parent"
            android:layout_marginLeft="5dp"
            android:gravity="center_vertical"
            android:text="Test Content 1"
            android:textSize="16sp"
            android:textColor="@color/black"/>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/black"
        />

</LinearLayout>

 

# RecyclerView에서 Item(항목)으로 사용할 Layout

 

 

2-4. list_footer.xml (리스트 푸터 레이아웃)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:background="#ededed"
    android:id="@+id/layoutListFooter"
    android:orientation="horizontal">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_baseline_add_circle_24"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="5dp"
        android:gravity="center_vertical"
        android:text="Item Add"
        android:textSize="20sp"
        android:textStyle="bold"
        android:textColor="@color/black"/>

</LinearLayout>

 

# RecyclerView에서 Footer로 사용할 Layout

 

 

 


3. ListAdapter.kt (리스트 어뎁터)

package com.example.recyclerview03

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import kotlinx.android.synthetic.main.list_footer.view.*
import kotlinx.android.synthetic.main.list_item.view.*

class ListAdapter(var list: ArrayList<String>): RecyclerView.Adapter<ListAdapter.ListViewHolder>() {
    val HEADER = 1
    val ITEM = 2
    val FOOTER = 3

    class ListViewHolder(val layout: View): RecyclerView.ViewHolder(layout)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
        var view =
            when(viewType) {
                HEADER ->
                    LayoutInflater.from(parent.context).inflate(R.layout.list_header, parent, false)
                FOOTER ->
                    LayoutInflater.from(parent.context).inflate(R.layout.list_footer, parent, false)
                else ->
                    LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
            }

        return ListViewHolder(view)
    }

    override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
        if(position == 0) {
            // HEADER
        } else if(position == list.size + 1) {
            // FOOTER
            holder.layout.layoutListFooter.setOnClickListener {
                list.add("")
                this.notifyDataSetChanged()
            }
        } else {
            // ITEM
            holder.layout.textListTitle.text = "Title $position"
            holder.layout.textListContent.text = "Contents $position"
        }
    }

    override fun getItemCount(): Int {
        return list.size + 2
    }

    override fun getItemViewType(position: Int): Int {
        return if(position == 0) {
            HEADER
        } else if(position == list.size + 1) {
            FOOTER
        } else {
            ITEM
        }
    }
}

 

# getItemViewType 함수를 override 한다.

 

그리고 position 값이 0 즉 맨 앞일 경우 HEADER의 값을 보내어 onCreateViewHolder에서 Header용으로 구성한 레이아웃을 불러오도록 한다.

 

이후 onBindViewHolder에서도 position 값에 따라서 값처리를 구분해주면 된다.

 

같은 방식으로 Footer 또한 구성 및 처리가 가능하다.

 

※ onBindViewHolder에서도 반드시 구분을 해주어야 한다. 각 layout마다 포함된 View Object가 다르기 때문에 구분을 해주지 않는다면, Header 레이아웃을 불러왔지만 Footer View Object의 접근하여 동작을 지정하고자 하는 것처럼 에러 발생의 원인이 될 수 있다.

 

 

 

 

# Item(항목)이 하나도 없을 경우에도 Header와 Footer를 보여주기 위해서 getItemCount에서 Item의 개수의 +2를 해주어야 한다.

 

따라서 Item이 하나도 없을 경우에도 Size는 0 + 2 = 2로서 Header/Footer가 표시된다.

 

 

※ 리사이클러뷰를 여러 곳에서 사용하거나 Header/Footer를 고정된 형태로 구성하고자 하면 Recyclerview를 선언한 Layout에서 위아래의 View Object를 구성하는 것도 하나의 방법이다.

(위 예시에서는 activity_main.xml 속 recyclerview 위 아래의 view 구성)

 

 


4. MainActivity.kt 

package com.example.recyclerview03

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var list = arrayListOf<String>()
        var listManager = LinearLayoutManager(this)
        var listAdapter = ListAdapter(list)

        var recyclerView = recyclerList.apply {
            setHasFixedSize(true)
            layoutManager = listManager
            adapter = listAdapter
        }
    }
}

 

# MainActivity 코드는 이전 간단한 RecyclerView를 선언했을 때와 동일한 구성

 

 

Android Kotlin RecyclerView - 리사이클러뷰(가로, 세로)

1. 결과 2. activity_main.xml (메인 레이아웃) # 1번 째 리사이클러 뷰는 Vertical(세로) 방향의 리사이클러 뷰 # 2번 째 리사이클러 뷰는 Horizontal(가로) 방향의 리..

notepad96.tistory.com

 

 

 


5. 전체 코드

 

GitHub - Notepad96/BlogExample

Contribute to Notepad96/BlogExample development by creating an account on GitHub.

github.com

 

 

 

 

300x250