Kotlin

[android : kotlin] 코틀린 리스트 뷰( ListView ) Custom Adapter 사용 예제

리스트뷰(ListView)는 여러 항목들을 제공하고, 스크롤 가능한 항목을 나타낼 때 사용되는 뷰 그룹이다. ListView에 먼저 View를 배치 후 데이터를 View의 형식에 맞게 변환하여 가져온다. 리스트뷰를 구성하기 위해서는 adapter(어댑터) 객체를 생성 후 설정해야한다. OnItemClickListener()는 리스트뷰의 항목을 클릭했을때 반응하는 이벤트 리스너이다.

커스텀 리스트 뷰를 사용해야하는 경우는 첫 번째로 기본적으로 지원하는 simple_list_item_1.xml의 텍스트뷰를 개발자가 원하는 글씨크기와 색상등을 변경하고자 할 때 사용된다. 두 번째는 항목이 하나가 아닌 여러개의 항목(데이터)을 리스트 뷰로 보여주기 위해서 사용된다. 그럼 본론으로 들어가서 Custom Adapter는 리스트 뷰를 구현할 때 개발자가 원하는 방향으로 기능을 추가하고 싶은 경우 SimpleAdapter 혹은 ArraryAdapter를 사용하지 않고 BaseAdapter클래스를 상속받아 직접 Adapter를 생성하는 방법이다. Adapter를 생성시 기본적인 메서드 2가지가 있다.  하나는 getCount()이며, 리스트뷰 내의 전체 항목의 개수를 리턴한다. 또 하나의 메서드는 getView()메서드로 리스트 뷰의 항목 하나를 구성하여 리턴 한다.

 

[MainActivity.kt]

package edu.kotlin.study

import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.*
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.textView1
import kotlinx.android.synthetic.main.custom_simple_list_item_1.*

class MainActivity : AppCompatActivity() {
    var dataArr = arrayOf("사과", "복숭아", "오렌지", "자두")
    var dataArr2 = arrayOf("apple", "peach", "orange", "plum")


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

        listview1.adapter = MyListAdapter()
        //ArrayAdapter(this, R.layout.custom_simple_list_item_1, R.id.textView1, dataArr)

    }

    inner class MyListAdapter : BaseAdapter() {
        //var globalPosition: Int = 0

        override fun getCount(): Int {
            return dataArr.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? {
            var myConverView: View? = convertView  //재사용 가능한 뷰가 넘어온 경우
            if(convertView == null) {
                myConverView = layoutInflater.inflate(R.layout.custom_simple_list_item_1, null)
            }

            var text1: TextView? = myConverView?.findViewById<TextView>(R.id.textView1)


            var button1: Button? = myConverView?.findViewById<Button>(R.id.button1)
            var button2: Button? = myConverView?.findViewById<Button>(R.id.button2)

            button1?.setOnClickListener(ButtonOnClickListener())
            button2?.setOnClickListener(ButtonOnClickListener())

            //globalPosition = position

            button1?.tag = position
            button2?.tag = position


            text1?.text = dataArr[position]

            return myConverView
        }

    }

    inner class ButtonOnClickListener : View.OnClickListener {

        override fun onClick(v: View?) {

            var position = v?.tag as Int

            when(v?.id) {
                R.id.button1 ->
                    textView1.text = "$position 번째 항목 clicked"
                R.id.button2 ->
                    textView1.text = "$position 번째 항목 clicked2"
            }
        }

    }

}

[activity_main.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="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="리스트뷰"
        android:textAppearance="@style/TextAppearance.AppCompat.Display2" />

    <ListView
        android:id="@+id/listview1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

[custom_simple_list_item_1.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="wrap_content"
    android:gravity="center|left"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:srcCompat="@drawable/ic_launcher_foreground" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="아이템"
            android:textAppearance="@style/TextAppearance.AppCompat.Display2"
            android:textColor="@color/colorPrimary" />

        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />
        <Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />
    </LinearLayout>
</LinearLayout>

 

[build.gradle(:app)] 

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29

    defaultConfig {
        applicationId "edu.kotlin.study"
        minSdkVersion 22
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

ListView는 Adapter를 통해 getView 메서드를 호출하여 View를 만든다. 최초로 화면을 로딩한 후에도 스크롤을 움직이는 등 액션을 취하면 그 때마다 findViewById를 통해 convertView에 들어갈 요소를 찾기 때문에 리소스를 많이 사용하게 되고 속도가 느려지는 단점을 가지고 있다. 리스트 뷰의 단점을 보완하기 위해 리사이클러뷰(RecyclerView)가 지원됨으로 되도록이면 리스트뷰의 사용 보다는 리사이클러뷰의 사용을 추천한다.

 

Leave a Reply

error: Content is protected !!