Archives
Recent Posts
«   2025/06   »
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
29 30
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[32일차 Android] ListView - CustomAdapter 본문

Computer/Android

[32일차 Android] ListView - CustomAdapter

Wise-99 2023. 6. 15. 12:35

 

 

 

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

 

 

 

📖 CustomAdapter

  • AdapterView 자체를 커스터마이징하여 특별한 기능을 부여하기 위해 Adapter 클래스를 구현한다.

BaseAdapter

  • BaseAdapter를 상속받아 다음 메서드를 구현한다.
    • getCount : AdapterView를 통해 보여줄 항목의 개수를 반환
    • getView : AdapterView를 통해 보여줄 항목의 View를 반환

 

 

 

예제 코드

row.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="match_parent"
    android:orientation="horizontal"
    android:padding="10dp">

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

    <Button
        android:id="@+id/buttonRow1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="버튼1" />

    <Button
        android:id="@+id/buttonRow2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="버튼2" />
</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"
    android:padding="10dp"
    tools:context=".MainActivity" >

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

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

 

 

 

MainActivity.kt

package com.test.android33_customadapter

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import com.test.android33_customadapter.databinding.ActivityMainBinding
import com.test.android33_customadapter.databinding.RowBinding

class MainActivity : AppCompatActivity() {

    lateinit var activityMainBinding: ActivityMainBinding

    val data1 = arrayOf(
        "데이터1", "데이터2", "데이터3", "데이터4", "데이터5"
    )

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

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

        activityMainBinding.run {
            listView.run {
                adapter = CustomAdapter()
            }
        }
    }

    // AdapterClass
    inner class CustomAdapter : BaseAdapter() {
    
        override fun getCount(): Int {
            return data1.size
        }
        
        override fun getItem(position: Int): Any? {
            return null
        }
        
        override fun getItemId(position: Int): Long {
            return 0
        }
        
        override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
            // layout binding 객체를 담을 변수
            var rowBinding : RowBinding? = null
            // 항목 View를 담을 변수
            var mainView = convertView

            if(mainView == null){
                rowBinding = RowBinding.inflate(layoutInflater)
                mainView = rowBinding.root
                mainView!!.tag = rowBinding
            }
            else {
                rowBinding = mainView!!.tag as RowBinding
            }

            rowBinding.run {
                textViewRow1.run {
                    text = data1[position]
                }

                buttonRow1.run {
                    setOnClickListener {
                        activityMainBinding.textViewResult.text = "$position : 버튼1"
                    }
                }

                buttonRow2.run {
                    setOnClickListener {
                        activityMainBinding.textViewResult.text = "$position : 버튼2"
                    }
                }
            }
            return mainView
        }
    }
}

코드 리뷰

  • adapter = CustomAdapter() : ListView의 adapter를 CustomAdapter()로 설정한다.

 

  • inner class CustomAdapter : BaseAdapter() { ... }
    • BaseAdapter를 상속받아 메서드를 구현한다. 
      • override fun getCount(): Int { ... } : ListView의 row 수를 결정하는 메서드로, 이 메서드가 반환하는 정수만큼 row를 생성한다.
      • override fun getItem(position: Int): Any? { ... } : 현재 번째의 row View를 반환한다.
      • override fun getItemId(position: Int): Long { ... } : 현재 번째의 로우 View의 ID를 반환한다.
      • override fun getView(position: Int, convertView : View?, parent: ViewGroup?): View { ... }
        • row로 사용할 View를 생성하여 반환하는 메서드
        • 여기서 반환하는 View를 현재 번째의 row로 사용한다.
        • position : 구성하고자 하는 row의 순서 값으로 0부터 1씩 증가한다.
        • convertView : 재사용 가능한 View가 있다면 해당 매개 변수에 들어온다.
        • if(mainView == null){ ... }
          • 재사용 가능한 View가 없다면 rowBinding 객체를 생성한다.
          • 생성한 rowBinding 객체를 tag를 이용하여 View에 저장한다.
        • else { ... }
          • 재사용 가능한 View가 있다면 View에 저장한 rowBinding 객체를 추출한다.
        • rowBinding.run { ... }
          • 추출한 rowBinding 객체를 이용하여 textViewRow1의 text와 button의 setOnClickListener를 설정한다.