[Kotlin] ListView 정리

ddwwon·2022년 11월 3일
0

Android

목록 보기
8/8
post-thumbnail

1. MainActivity에 ListView 추가

1) activity_main.xml의 기본 Layout은 LinearLayout으로 설정
2) LinearLayout내에 ListViewmatch_parent로 설정
3) ListViewid값 설정

<?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"
    tools:context=".MainActivity">

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

    </ListView>

</LinearLayout>

2. ListView에 넣을 item_layout 생성

1) layout 폴더에 item_layout을 생성한다.
➡️ listview_item.xml 생성
간단한 명함 형태의 layout 제작

<?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:weightSum="5">

    <ImageView
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        android:src="@mipmap/ic_launcher"/>

    <LinearLayout
        android:layout_weight="3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical">
        <TextView
            android:id="@+id/name_listview_item"
            android:text="이름"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/contents_listview_item"
            android:text="내용"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <Switch
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_gravity="center"
        android:layout_height="wrap_content"/>

</LinearLayout>

3. activity_main.xml의 listview에 item_layout 추가

activity_main.xml에 있는 listviewtools:listitem을 사용해서 item_layout과 listview를 연결해준다.
이때 item_layout = listview_item

<?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"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listview_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@layout/listview_item"/>

</LinearLayout>

4. item_layout에서 지금 변화하는 데이터들을 데이터 클래스에 묶는다.

1) MainActivity.kt에서 data class를 사용해서 데이터를 묶는다.

data class BusinessCard(val name: String, val contents: String)

2) ArrayList를 사용해서 변화하는 데이터 생성

var businesCardArrayList = ArrayList<BusinessCard>()

5. ListView에 data를 연결하기 위해 Adapter를 생성해준다.

1) CustomAdapter.kt 생성
2) CustomAdapter가 Adapter로서 기능을 하려면 Base Adapter를 상속 받아야 한다.
특히 ListView의 Adapter만 Base Adapter를 상속받는다. RecyclerView와 다르다!

import android.widget.BaseAdapter

3) 생성자로는 Context, ArrayList

class CustomAdapter(context: Context, private val businessCardArraylist:ArrayList<BusinessCard>):BaseAdapter()

BaseAdapter가 추상 클래스 이기 때문에 Error 발생
➡️ Implement members를 해서 모든 함수를 override 해주면 해결!
위에서 생성한 ArrayList에 데이터 타입을 맞춰 Adapter에서도 동일한 데이터 타입의 ArrayList로 받아준다.
4) layout inflater 중요!

val inflater  = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

context.getSystemService
시스템에 있는 API를 호출해서 애플리케이션에서 쓸 수 있게 한다. 즉, 애플리케이션과 OS 사이에 중재자라고 볼 수 있다.
getView를 사용하기 위해서 inflate 작업 필요하다. inflater를 통해서 시스템에 대한 권한을 부여 받는다.
5) ViewBinding

lateinit var binding : ListviewItemBinding

6) getCount()

override fun getCount(): Int = businessCardArraylist.size

ArrayList의 size를 반환해준다.
7) getItem()

override fun getItem(position: Int): Any = businessCardArraylist[position]

위치 값에 따른 데이터를 반환해준다.
8) getItemId()

override fun getItemId(position: Int): Long = position.toLong()

getItemId 포지션 값을 반환해준다.
9) getView()

binding = ListviewItemBinding.inflate(inflater, parent, false)
        binding.nameListviewItem.text = businessCardArraylist[position].name
        binding.contentsListviewItem.text = businessCardArraylist[position].contents

최초 호출될 때, 화면 크기만큼 item_layout(listview_item)이 들어갈 수 있는 공간을 채울 때 호출 된다.
그 후 스크롤 시 아이템이 보일 때마다 호출이 되는 함수이다.
item_view에 있는 name_listview_itemcontents_listview_item의 위치에 맞는 데이터를 세팅한다. 스크롤이나 최초 시점에 순서에 맞게 데이터를 넣어준다.
inflater를 사용해 xml을 메모리에 올려준다.

  • 전체 코드(CustomAdapter.kt)
package com.example.listview_practice

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import com.example.listview_practice.databinding.ListviewItemBinding

class CustomAdapter(context: Context, private val businessCardArraylist:ArrayList<BusinessCard>):BaseAdapter() {

    val inflater  = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    lateinit var binding : ListviewItemBinding

    override fun getCount(): Int = businessCardArraylist.size
    override fun getItem(position: Int): Any = businessCardArraylist[position]

    override fun getItemId(position: Int): Long = position.toLong()

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        binding = ListviewItemBinding.inflate(inflater, parent, false)
        binding.nameListviewItem.text = businessCardArraylist[position].name
        binding.contentsListviewItem.text = businessCardArraylist[position].contents

        return binding.root
    }
}

6. MainActivity.kt에서 Adapter를 만들고, ListView에 세팅을 해준다.

1) lateinit으로 Adapter 선언
ArrayList에 데이터를 초기화한 다음에 세팅하기 위해서~
2) Adapter에 ArrayList를 추가해서 넘겨준다.

customAdapter = CustomAdapter(this, businesCardArrayList)

3) ListView에 Adapter를 넣어준다.

binding.listviewMain.adapter = customAdapter
  • 전체 코드(MainActivity.kt)
package com.example.listview_practice

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.service.voice.VoiceInteractionSession
import com.example.listview_practice.databinding.ActivityMainBinding
import com.example.listview_practice.databinding.ListviewItemBinding

data class BusinessCard(val name: String, val contents: String)

class MainActivity : AppCompatActivity() {

    var businesCardArrayList = ArrayList<BusinessCard>()
    private lateinit var customAdapter: CustomAdapter
    lateinit var binding: ActivityMainBinding

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

        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        for(x in 0..30)
        {
            businesCardArrayList.add(BusinessCard("도원", "하이룽"))
        }

        customAdapter = CustomAdapter(this, businesCardArrayList)
        binding.listviewMain.adapter = customAdapter
    }
}

0개의 댓글