Archives
Recent Posts
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[32일차 Android] RecyclerView 본문

Computer/Android

[32일차 Android] RecyclerView

Wise-99 2023. 6. 16. 08:06

 

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 RecyclerView

  • Adapter를 직접 구현해 줘야 하며 이를 통해 항목을 자유롭게 구성할 수 있다.
  • 반드시 항목들을 어떠한 형태로 보여줄 것인가를 설정해야 한다.

AdapterClass 구현

1. 아무 것도 상속받지 않은 클래스를 만들어준다.
2. ViewHolder를 만들어준다.
3. AdapterClass를 RecyclerView.Adapter를 상속받게 한다.

항목 배치

  • RecyclerView는 ListView와 GridView를 통합한 View이다. 따라서 ListView 처럼 보여줄 것인지 GridView 처럼 보여줄 것인지 결정해야 한다.
    • LinearLayoutManager : ListView처럼 항목을 보여준다.
    • GridLayoutManager : GridView처럼 항목을 보여준다.
    • StaggerGridLayoutManager : GridView처럼 보여주지만 완전한 그리드가 아닌 각 항목의 크기에 따라 유동적으로 조절된다.

 

 

 

예제 코드

row.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/imageViewRow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/textViewRow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:text="TextView"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</LinearLayout>

 

 

 

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">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />

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

 

 

 

MainActivity.kt

package com.test.android36_recyclerview

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.test.android36_recyclerview.databinding.ActivityMainBinding
import com.test.android36_recyclerview.databinding.RowBinding

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding
    val imgRes = intArrayOf(
        R.drawable.imgflag1,
        R.drawable.imgflag2,
        R.drawable.imgflag3,
        R.drawable.imgflag4,
        R.drawable.imgflag5,
        R.drawable.imgflag6,
        R.drawable.imgflag7,
        R.drawable.imgflag8
    )

    val data1 = arrayOf(
        "토고", "프랑스 문자열을 길게 작성해주세요 문자열을 길게 작성해주세요 문자열을 길게 작성해주세요",
        "스위스", "스페인",
        "일본 문자열을 길게 작성해주세요 문자열을 길게 작성해주세요 문자열을 길게 작성해주세요",
        "독일", "브라질", "대한민국"
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)

        activityMainBinding.run {
            recyclerView.run{
                adapter = RecyclerAdapterClass()
                // 위에서 아래 방향으로
                layoutManager = LinearLayoutManager(this@MainActivity)

                // 그리드
                // layoutManager = GridLayoutManager(this@MainActivity, 2)

                // StaggeredGridLayoutManager는 항목 View의 크기는 필요한 만큼만 사용하고
                // 화면에 빈칸이 없도록 배치를 조정해준다.
                // 세로 방향
                // layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
                // 가로 방향
                // layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL)
            }
        }
    }

    // RecyclerView의 AdapterClass
    inner class RecyclerAdapterClass : RecyclerView.Adapter<RecyclerAdapterClass.ViewHolderClass>(){

        inner class ViewHolderClass(rowBinding: RowBinding) : ViewHolder(rowBinding.root), OnClickListener{
            var textViewRow:TextView
            var imageViewRow:ImageView

            init {
                textViewRow = rowBinding.textViewRow
                imageViewRow = rowBinding.imageViewRow
            }

            override fun onClick(v: View?) {
                activityMainBinding.textView.text = data1[adapterPosition]
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderClass {
            // ViewBinding
            val rowBinding = RowBinding.inflate(layoutInflater)
            // ViewHolder
            val viewHolderClass = ViewHolderClass(rowBinding)

            // 클릭 이벤트를 설정해준다.
            rowBinding.root.setOnClickListener(viewHolderClass)

            val params = RecyclerView.LayoutParams(
                // 가로 길이
                RecyclerView.LayoutParams.MATCH_PARENT,
                // 세로 길이
                RecyclerView.LayoutParams.WRAP_CONTENT
            )
            rowBinding.root.layoutParams = params

            return viewHolderClass
        }

        // 전체 행의 개수를 반환한다.
        override fun getItemCount(): Int {
            return imgRes.size
        }

        override fun onBindViewHolder(holder: ViewHolderClass, position: Int) {
            holder.textViewRow.text = data1[position]
            holder.imageViewRow.setImageResource(imgRes[position])
        }
    }
}

코드 리뷰

  •  layoutManager = LinearLayoutManager(this@MainActivity) 
    • Layout을 어떻게 보여줄 것인가를 설정한다.
    • LinearLayout은 위에서 아래 방향으로 설정된다.

 

  •  layoutManager = GridLayoutManager(this@MainActivity, 2) 
    • 한 줄에 몇칸을 사용할 것인지 설정할 수 있다.
    • 해당 코드는 한 줄에 두 칸을 사용한다.
    • 1로 설정하면 LinearLayoutManager와 동일하다.

 

  •  layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL) 
    • 항목 View의 크기는 필요한 만큼만 사용하고 화면에 빈 칸이 없도록 배치를 조정해준다.
    • 해당 코드는 VERTICAL로 설정하여 세로 방향으로 보여준다.

 

  •  layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL) 
    • 해당 코드는 HORIZONTAL로 설정하여 가로 방향으로 보여준다.
  • inner class ViewHolderClass((rowBinding: RowBinding) : ViewHolder(rowBinding.root), OnClickListener{ ... }
    • RecyclerView의 Row 하나가 가지고 있는 View들의 객체의 Id 값을 가지고 있는 Holder Class
    • 주 생성자로 ViewBinding 객체를 받는다.
    • 부모의 생성자에게 행 하나로 사용할 View를 전달한다.
  •  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderClass { ... } 
    • ViewHolder의 객체를 생성해서 반환한다.
    • 전체 행의 개수가 아닌 필요한 만큼만 행으로 사용할 View를 만들고 ViewHolder도 생성한다.
    • val params = RecyclerView.LayoutParams( ... ) : 항목 View의 가로, 세로 길이를 설정해준다.
  •  override fun getItemCount() : Int { ... } 
    • 전체 행의 개수를 반환한다.
  •  override fun onBindViewHolder(holder: ViewHolderClass, position: Int) { ... } 
    • viewHolder를 통해 View에 접근하여 View에 값을 설정한다.
    • 첫번째 매개 변수 : ViewHolder 객체
    • 두번째 매개 변수 : 특정 행의 순서 값

'Computer > Android' 카테고리의 다른 글

[34일차 Android] Option Menu  (0) 2023.06.17
[33일차 Android] Permission  (0) 2023.06.17
[32일차 Android] Spinner  (0) 2023.06.16
[32일차 Android] ListView - CustomAdapter  (0) 2023.06.15
[31일차 Android] ListView - SimpleAdapter  (0) 2023.06.15