스터디/Android+Kotlin

안드로이드 코틀린으로 리스트 만들기 (RecyclerView)

Dalmangyi 2020. 7. 5.

안녕하세요!

안드로이드 스튜디오4.0에서 코틀린으로 안드로이드 리스트(리스트뷰)를 만들어보도록 하겠습니다~

이번 글에서는 데이터의 갯수가 미리 정해져있는 리스트뷰를 만들어보겠습니다.

좀 게시글이 기니까 마음 단단히 잡고 따라오세요!!

 

 

목차는 다음과 같습니다

  • 리스트 개요
  • 리스트뷰 요소 5가지
    • 데이터
    • 스크롤영역
    • 뷰홀더
    • 어댑터
    • 레이아웃 매니저
  • 프로젝트 생성
  • 환경세팅
    • Dependencies 추가
    • Activity 만들기
      • Layout 만들기
      • Activity 클래스 만들기
      • AndroidManifest에 Activity 추가하기
  • 리스트뷰 만들기 (1) : 데이터
    • Data 클래스 만들기
    • Data 샘플 만들기
  • 리스트뷰 만들기(2) : ScrollArea
    • XML 추가하기
    • 중간점검
  • 리스트뷰 만들기(3) : ViewHolder
    • XML 만들기
    • ViewHolder 클래스 만들기
  • 리스트뷰 만들기(4) : Adapter
    • Adapter 클래스 만들기 
    • Adapter 적용하기
  • 리스트뷰 만들기(5) : LayoutManager
    • XML 만들기
  • 완성모습
  • 마무리

 

 

 


 

 

리스트

리스트는 우리가 흔하게 접하는 화면 표현방식입니다.

뉴스를 보거나 메일을 읽거나 사진첩을 보거나 전화번호부를 볼 때 대부분 리스트로 구현되어 있습니다.

한정된 공간에서 규칙적인 많은 데이터를 보여줄때 이것처럼 효율적인건 찾아 보기 힘들죠.

그래서 꼭 리스트는 만들 줄 알아야 합니다.

구글 '리스트뷰' 검색결과

 

 

 

리스트뷰가 꼭 세로만 있는건 아닙니다

리스트뷰는 기본적으로 스크롤을 가지고 있는 뷰 이기때문에 가로로된 리스트뷰, 바둑판 형식의 리스트뷰도 존재합니다

넷플릭스 앱 스크린샷

 

넷플릭스 앱만 보더라도 수많은 리스트뷰가 혼용되어 있는걸 볼 수 있습니다.

전체적으로 세로로 된 리스트지만, 각 칸은 가로 리스트뷰로 되어 있는걸 알 수 있습니다.

 

 

이번 강좌에서는 일반적인 리스트뷰 보다는

메모리 최적화 기능이 있고, 좀 더 편하게 개발할 수 있는

리사이클러뷰(RecyclerView)를 개발해 보겠습니다

 

 

 

 


 

리스트뷰 요소

리스트뷰는 크게 5가지 요소(Data, ScrollArea, ViewHolder, Adapter, LayoutManager)로 나뉠 수 있습니다

(제 기준으로 나눴습니다 '-'...)

 

1. 데이터 (Data)

리스트뷰를 보여줄 일관된 규칙을 가진 데이터들이 필요합니다

서로 다른 규칙을 가진 데이터들이라면 리스트뷰로 만들지 말고, 일반 뷰를 합쳐보이는게 나은 경우가 많습니다

 

2. 스크롤영역 (ScrollArea)

리스트뷰를 보여줄 화면 영역입니다

많은 양의 데이터를 보여주려면 글씨를 작게해서 표현해야되는데 그것도 한계가 있게되죠

그래서 안보이는 영역에 데이터가 존재하니 참고해라라는 뜻으로 스크롤이 필요합니다

물론 스크롤바는 보이지 않아도 됩니다

 

3. 뷰홀더 (ViewHolder)

데이터가 적용될 반복되는 뷰를 말합니다

매번 뷰를 그리게 되면 메모리를 많이 차지 하기때문에

같은 규칙을 가진 데이터들을 표현할땐 뷰를 재활용해서 사용하게 됩니다

뷰의 구성과 사이즈를 구정해놓고, 뷰 내부에 있는 Text나 Image를 주로 변경해서 재사용합니다. 

 

4. 어댑터 (Adapter)

어댑터는 함수 처럼 데이터를 컨트롤하는 역활을 합니다

데이터를 뷰홀더의 어떤 부분에 적용해야 하는지 설정해줍니다

예를 들면, 전화번호부 데이터가 있을때, 이름은 뷰홀더의 text1 부분에 적용하고, 전화번호는 뷰홀더의 text2부분에 적용시켜주는 역활을 할 수 있습니다. 

뷰홀더가 뷰를 담당한다면, 어댑터는 뷰홀더의 데이터를 담당합니다.

 

5. 레이아웃 매니저 (LayoutManager)

점점 다양해져가는 디자인 요구사항으로 인해 매번 어댑터를 컨트롤하기 힘들어서(귀찮아서) 생긴 개념입니다.

색 안경을 끼면 기존과 달라보이듯이 리스트뷰의 안경 역활을 하는 레이아웃 매니저는 리스트뷰의 레이아웃을 변경해줍니다

1줄에 1개의 칸이 있다면 LinearLayoutManager, 여러 칸이 있다면 GidLayoutManger로 불립니다.

 

 


 

프로젝트 생성

'+ Start a new Android Studio project' 클릭

 

 

'No Activity' > 'Next'

 

 

이름 짓기, Language:Kotlin, Min SDK:API23 > 'Finish'

 

 


 

 

환경세팅

리스트뷰의 5가지 요소를 개발하기 앞서 리스트뷰를 보여줄 환경 세팅이 필요합니다.

 

 

 


환경세팅 : Depencency 추가 

RecyclerView는 기본적을 안드로이드에 포함되어 있지 않습니다. 

그래서 androidx.recyclerview 디펜던시(라이브러리)를 추가해줘야합니다

app 폴더 안에 있는 build.grable 파일에 dependencies 부분에 아래와 같이 추가합니다.

dependencies {
	...
    implementation "androidx.recyclerview:recyclerview:1.1.0"
}

app/build.gradle

 

implementation 를 추가하고 'Sync Now'를 클릭합니다.

잠깐의 동기화 과정이 끝나면 프로젝트에서 recyclerview를 사용할 수 있게 됩니다.

 

 

 


환경세팅 : Activity 만들기

리스트뷰를 보여줄 액티비티를 만들어 봅시다

 

1. Layout 만들기

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

</RelativeLayout>

app/src/main/res/layout/activity_list.xml

 

 

 

2. Activity 만들기 

package com.example.mylistapplication

import android.app.Activity
import android.os.Bundle

class ListActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_layout)
    }
}

app/src/main/java/com.example.mylistapplication/ActivityList.kt

 

 

 

3. AndroidManifest에 Activity 추가하기

AndroidManifest.xml 파일에 아래처럼 <activity>태그와 <intent-filter>를 추가합니다

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mylistapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        
        <activity android:name=".ListActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

app/src/main/AndroidManifest.xml

 

 

 


중간점검

이쯤에서 한번 실행해 보겠습니다

아무것도 안보이는게 당연합니다!

Android Studio 툴 중에 'Layout Inspector'를 이용하면, 연결된 에뮬레이터의 앱 내부에 있는 레이아웃 구성을 상세하게 볼 수 있습니다.

Tools > Layout Inspector

 

 

Layout Inspector가 실행되면, 직접만든 레이아웃(activity_list.xml)이 Activity에 잘 반영된 걸 볼 수 있습니다.

RelativeLayout > ReclerView

 

 

 


리스트뷰 만들기(1) : 데이터

연락처 리스트가 나오는 리스트뷰를 만들어 보겠습니다.

 

1.Data 클래스 만들기

간단한 클래스를 만들어 보겠습니다

연락처 클래스 Contacts.kt 파일을 만들고, 생성자(Constructor)를 설정합니다

연락처 클래스(Contacts)는 이름(name)과 전화번호(tel)로 이루어져있습니다.

package com.example.mylistapplication

class Contacts(val name: String, val tel: String) {
}

app/src/main/java/com.example.mylistapplication/Contacts.kt

 

 

2.Data 샘플 만들기

데이터는 메인에 간단하게 전역변수 리스트 형식으로 만들어줍니다.

직접 전화번호부를 접근하기 위해선 이 게시글에서 너무 많은 양을 설명해야 됩니다... 그래서 간단하게 미리 정해놓고 시작해 봅시다.

john, mir, delp, jacob, sheu, ma, ham 의 전화번호를 리스트 형식(List<Contacts>)으로 추가했습니다

package com.example.mylistapplication

import android.app.Activity
import android.os.Bundle

class ListActivity : Activity() {

    val contactsList : List<Contacts> = listOf(
        Contacts("john","010-0000-11111"),
        Contacts("mir","010-1111-2222"),
        Contacts("delp", "010-3333-4444"),
        Contacts("jacob", "010-3333-5555"),
        Contacts("sheu", "010-3333-6666"),
        Contacts("ma", "010-3333-7777"),
        Contacts("ham", "010-3333-8889")
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_layout)


    }
}

app/src/main/java/com.example.mylistapplication/ListActivity.kt

 

 


리스트뷰 만들기(2) : ScrollArea

스크롤 영역은 RecyclerView를 XML에 추가해줍니다.

 

1. XML

RecyclerView를 전체 사이즈에 맞게 추가합니다.

뷰의 id는 Activity에서 바로 접근하기 좋은 이름(mRecyclerView)으로 지어줬습니다

tip. id 값은 안드로이드 개발자들은 항상 태그 아래쪽에 배치합니다. 그래야 찾기가 쉬워요!

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

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

app/src/main/res/layout/activity_list.xml

 

 

 

 

2. 중간점검

Layout Inspector가 실행되면 작성한 recyclerView가 Activity에 잘 반영된 걸 볼 수있습니다.

심지어 저희가 만든 id까지 반영되는게 보이네요!

RelativeLayout > ReclerView : mRecyclerView

 

 

 


리스트뷰 만들기(3) : ViewHolder

1. XML

ViewHolder에 사용될 레이아웃 XML을 res/layout/item_contacts.xml 로 만듭니다

간단하게 레이아웃 위에는 이름, 아래는 전화번호 입니다.

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

    <TextView
        android:id="@+id/mName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/mTel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

app/src/main/res/layout/item_contacts.xml

 

 

2. ViewHolder

RecyclerView의 어뎁터에 사용할 뷰홀더를 com.example.mylistapplication.ContactsViewHolder.kt로 만듭니다

ViewHolder 레이아웃에 있는 mName과 mTel 부분에, 인자로 받은 Contacts의 변수 name과 tel을 각각 연결해줍니다

package com.example.mylistapplication

import android.view.View
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_contacts.view.*

class ContactsViewHolder(v: View) : RecyclerView.ViewHolder(v) {
    var view : View = v
    
    fun bind(item: Contacts) {
        view.mName.text = item.name
        view.mTel.text = item.tel
    }
}

app/src/main/java/com.example.mylistapplication/ContactsViewHolder.kt

 

 


리스트뷰 만들기(4) : Adapter

1. Adapter 클래스 만들기 

com.example.mylistapplication.ContactsListAdapter.kt 파일을 만들고,

ContactsListAdapter 클래스에 생성자 파라매터 List<Contacts>를 추가해줍니다.

class ContactsListAdapter(val itemList : List<Contacts>) : RecyclerView.Adapter<ContactsViewHolder>()  {
}

app/src/main/java/com.example.mylistapplication/ContactsListAdaper.kt

 

 

1) getItemCount()
생성자로 부터 받은 데이터의 갯수를 측정해야 합니다

이 함수는 데이터를 상세 컨트롤 할 수 있게 return 으로 adapter에게 알려주는 역활을 합니다

override fun getItemCount(): Int { 
	return itemList.size
}

app/src/main/java/com.example.mylistapplication/ContactsListAdaper.kt

 

 

2) onCreateViewHolder() 

Adapter에서 사용할 ViewHolder를 설정해 줍니다

LayoutInflater를 이용해서 item_contacts.xml 정보를 가져옵니다

inflatedView를 사용한 ContactsViewHolder를 반환합니다

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactsViewHolder {
	val inflatedView = LayoutInflater.from(parent.context)
		.inflate(R.layout.item_contacts, parent, false)
	return ContactsViewHolder(inflatedView);
}

app/src/main/java/com.example.mylistapplication/ContactsListAdaper.kt

 

 

3) onBindViewHolder()

viewHolder의 apply 함수를 이용해서 bind 함수를 호출해서

각각의 데이터를 item_contacts를 사용하는 ViewHolder에 적용합니다.

override fun onBindViewHolder(holder: ContactsViewHolder, position: Int) {
	val item = itemList[position]
	holder.apply {
		bind(item)
	}
}

app/src/main/java/com.example.mylistapplication/ContactsListAdaper.kt

 

 

4) ContactsListAdapter 클래스

위 코드를 다 적은 모습입니다

package com.example.mylistapplication

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

class ContactsListAdapter(private val itemList : List<Contacts>) : RecyclerView.Adapter<ContactsViewHolder>()  {

    override fun getItemCount(): Int {
        return itemList.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactsViewHolder {
        val inflatedView = LayoutInflater.from(parent.context).inflate(R.layout.item_contacts, parent, false)
        return ContactsViewHolder(inflatedView);
    }

    override fun onBindViewHolder(holder: ContactsViewHolder, position: Int) {
        val item = itemList[position]
        holder.apply {
            bind(item)
        }
    }

}

app/src/main/java/com.example.mylistapplication/ContactsListAdaper.kt

 

 

2. Adapter 적용하기

DataBinding (kotlinx)를 이용해서 activity_layout에 작성해둔 mRecyclerView의 adapter에

직접 만든 ContactsListAdapter를 설정합니다.

 

DataBinding을 이용하면 xml파일에 있는 id에 바로 접근할 수 있게 도와줍니다. 

activity_layout.xml에 바로 접근할수 있도록 자동생성된 코드가 import 된것을 확인 할 수 있습니다.
(import kotlinx.android.synthetic.main.activity_layout.*)

package com.example.mylistapplication

import android.app.Activity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_layout.*

class ListActivity : Activity() {

    val contactsList : List<Contacts> = listOf(
        Contacts("john","010-0000-11111"),
        Contacts("mir","010-1111-2222"),
        Contacts("delp", "010-3333-4444"),
        Contacts("jacob", "010-3333-5555"),
        Contacts("sheu", "010-3333-6666"),
        Contacts("ma", "010-3333-7777"),
        Contacts("ham", "010-3333-8889")
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_layout)

        val adapter = ContactsListAdapter(contactsList)
        mRecyclerView.adapter = adapter
    }
}

app/src/main/java/com.example.mylistapplication/ListActivity.kt

 

 


리스트뷰 만들기(5) : LayoutManager

1. XML적용

전화번호부는 세로에 1칸씩 있는 리스트뷰면 충분하기 때문에,

여러 방법이 있겠지만, app:layoutManager 속성을 이용하여서

RecyclerView에 LinearLayoutManager를 할당해 줍니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/mRecyclerView"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

</RelativeLayout>

app/src/main/res/layout/activity_list.xml 

 

 


완성 모습


 

마무리

 

여러울거 같았던 리스트가 정말 쉽게 구현이 되었고 

리스트를 구성하는 요소들이 모듈화가 잘 되어 있음을 느낄 수 있었습니다

 

리스트의 클릭기능까지 추가하기엔, 내용이 길거 같아 이정도로 마무리하고,

다음 게시글에서 찾아 뵙겠습니다

 

부족한 부분은 댓글로 달아주시면

빠른시일내에 업데이트 해놓겠습니다!

 

 

 

 


다음 목차

다음 목차는 이 게시글에 이어지는 내용입니다.

다음 게시글에서는 리사이클러뷰에 클릭을 달아보겠습니다!

dalgonakit.tistory.com/139

 

안드로이드 코틀린으로 만든 리사이클러뷰(RecyclerView)에 클릭 기능 추가하기 (Add ClickListener)

안녕하세요 ! 오늘은 지난번 만든 리스트 앱에 클릭 기능을 추가해보도록 하겠습니다. ❖ 지난 게시글에 이어지는 게시글입니다.  https://dalgonakit.tistory.com/138 안드로이드 코틀린으로 리스트 만

dalgonakit.tistory.com

 

댓글