android studio) ListView 이용하기

김범기·2024년 4월 2일

android studio

목록 보기
1/1

ListView?

인프런에서 강의를 듣던 중 ListView에 대한 내용이 나왔는데, 나에겐 어렵게 느껴져서 필기 겸 해서 작성해보려한다.

listView가 뭔데?

사진에서 보이듯, 흔히 볼 수 있는 리스트 그러니까 목록을 죽 나열해서 보여주는 녀석이라 보면 되겠다.

android studio에서의 작동 형태

MainActivity에서 Adapter로 데이터를 전송
Adapter에서 listview_item.xml에 item(쉽게 목록 1줄)에 "a","b","c"를 하나씩 넣어준 후 이를 acitivity_main.xml의 ListView에 넣어준다.

ListView 생성해보기

프로젝트 생성

ListView 생성

res - layout-activity_main.xml에 ListView를 생성해주기

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

어뎁터 생성해주기

MainActivity가 있는 폴더에 이름을 ListViewAdapter 로 kotlin 파일을 생성.

package com.blueblue.listview_ex

class ListViewAdapter {
}

어떤 리스트를 받을지 입력

package com.blueblue.listview_ex

import android.widget.BaseAdapter

class ListViewAdapter(val List : MutableList<String>): BaseAdapter(){
}


빨간 줄 뜨는 곳에 alt+enter 눌러서 BaseAdapter로서 작동하게 하기 위해 import 및 코드 기입

package com.blueblue.listview_ex

import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter

class ListViewAdapter(val List : MutableList<String>): BaseAdapter() {
    override fun getCount(): Int {
        TODO("Not yet implemented")
    }

    override fun getItem(position: Int): Any {
        TODO("Not yet implemented")
    }

    override fun getItemId(position: Int): Long {
        TODO("Not yet implemented")
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        TODO("Not yet implemented")
    }
}

getCount: ListView의 갯수, 이번엔 입력받는 list의 크기로 설정
getItem: item에 들어갈 리스트의 원소
getPosition: 해당 item이 가지게 될 Id
getView: ListView의 각 항목을 위한 뷰를 생성하고 반환하는 역할

getView에 적용시킬 xml 생성

res-layout에서 layout Resource File을 추가 생성

이름은 상관없으나, listview_item으로 생성.(배우고 있는 중이니까)

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

</androidx.constraintlayout.widget.ConstraintLayout>

리스트의 각 아이템을 보여주는 공간으로 아래처럼 작성

<?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="80dp">

    <TextView
        android:id="@+id/listviewItem"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

Adapter에 코드 작성

getCount, getItem, getItemId에 사용할 리스트 사이즈와 원소, 아이템 id를 return 해주기
getView에서는 listview_item.xml을 가져와서 사용할 것임을 명시

ListViewAdapter에서 작성

package com.blueblue.listview_ex

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter

class ListViewAdapter(val List : MutableList<String>): BaseAdapter() {
    override fun getCount(): Int {
        return List.size
    }

    override fun getItem(position: Int): Any {
        return List[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var converView = convertView

        if(converView == null){
            converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
        }
        
        return converView!!
    }
}

MainActivity에서 Adapter로 데이터를 넣기

MainActivity에서 작성

package com.blueblue.listview_ex

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val list_item = mutableListOf<String>()

        list_item.add("A")
        list_item.add("B")
        list_item.add("C")

        val adapter = ListViewAdapter(list_item)
    }
}

리스트를 생성하고, 리스트에 "A","B","C" 를 각 원소로 기입 후

val listadapter = ListViewAdapter(list_item)

를 통해서 list_item을 MainActivity에서 Adapter 로 전달 완료.

남은 것은 listview_item.xml에서 activity_main.xml의 listview로 전달하는 과정!

listview로 전달하기

val listview = findViewById<ListView>(R.id.mainListview)

로 ListView 중에서 mainListview를 id로 사용하고 있는 LIstView를 listview 변수에 입력.

해당 변수를

listview.adapter = listadapter

adapter를 이용해서 이전에 만들어준 listadapter를 사용

package com.blueblue.listview_ex

import android.os.Bundle
import android.widget.ListView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val list_item = mutableListOf<String>()

        list_item.add("A")
        list_item.add("B")
        list_item.add("C")

        val listview = findViewById<ListView>(R.id.mainListview)

        val listadapter = ListViewAdapter(list_item)

        listview.adapter = listadapter
    }
}

그리고 run 해보면

내 ABC 어디감???

코드를 다시 살펴보면

ListViewAdapter의 getView에서

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var converView = convertView

        if(converView == null){
            converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
        }

        return converView!!
    }

converView(convertView말고) 는 layout의 listview_item.xml

즉, listview_item.xml에 있는 TextView가 된다.

<TextView
        android:id="@+id/listviewItem"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

그런데 여기에 데이터의 값을 이 TextView에 넣어주는 작업을 하지 않았으니 내 데이터로 목록이 뜨지 않음.

따라서 ListViewAdapter의 getView에

converView(null이 아님)에 속한 TextView중에 listviewItem이라는 녀석을 찾아서 title이라는 변수에 집어넣고, 이 title 즉, TextView의 text를 List[position] 으로 변경하겠다는

var title = converView!!.findViewById<TextView>(R.id.listviewItem)
        title.text = List[position]

이 코드를 추가해서 데이터가 입력되도록 한다.

그러면 잘 나오는 것을 확인할 수 있다.

정리

  1. MainActivity.kt에서 사용할 리스트가 있으시다!!!!
  2. activity_main.xml에 ListView를 생성!!!!
  3. 으아닛! 전달할 방법이 엄성.. adapter를 만들자!!! ListViewAdapter.kt 생성!(BaseAdapter를 통해 adapter로 사용)
  4. 메우, 리스트를 입력받았는데 얘 어떻게 보이게 할깝쇼? => listview_itme.xml을 만들어서 item을 생성하자!!!
  5. MainActivity.kt에서 adapter로 리스트를 전달전달영차영차!! 그리고, 연결시킬 ListView를 찾아서 연결하고, 출력준 비를 하라!!!!!
  6. ListViewAdapter.kt에서 MainActivity에서 하달하신 List를 적용하자!!! getView에서는 listview_item.xml을 연결시키고, 변환할 부분이 있으면 구현을 끝마치고, 반환하라!!!
  7. 완료ㅎ

MainActivity 코드

package com.blueblue.listview_ex

import android.os.Bundle
import android.widget.ListView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val list_item = mutableListOf<String>()

        list_item.add("A")
        list_item.add("B")
        list_item.add("C")

        val listview = findViewById<ListView>(R.id.mainListview)

        val listadapter = ListViewAdapter(list_item)

        listview.adapter = listadapter
    }
}

ListViewAdapter 코드

package com.blueblue.listview_ex

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

class ListViewAdapter(val List : MutableList<String>): BaseAdapter() {
    override fun getCount(): Int {
        return List.size
    }

    override fun getItem(position: Int): Any {
        return List[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var converView = convertView

        if(converView == null){
            converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
        }

        var title = converView!!.findViewById<TextView>(R.id.listviewItem)
        title.text = List[position]


        return converView!!
    }
}

activity_main.xml 코드

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

listview_item.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="80dp">

    <TextView
        android:id="@+id/listviewItem"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

model을 이용한다면?

이전과 틀은 동일.

ListViewModel.kt 생성

package com.blueblue.listview_ex

data class ListViewModel (
    var title : String = "",
    var content : String = ""
)

이렇게 ListViewModel로 title과 content를 가진 모델을 사용해보자.

MainActivity.kt

MainActivity.kt에서 사용되던 기존 코드는

val list_item = mutableListOf<String>()
        list_item.add("A")
        list_item.add("B")
        list_item.add("C")

        val listview = findViewById<ListView>(R.id.mainListview)

        val listadapter = ListViewAdapter(list_item)

        listview.adapter = listadapter

아래 처럼 model을 이용해서 list에 입력 시켜준다.

        val list_item = mutableListOf<ListViewModel>()
        list_item.add(ListViewModel("a","b"))
        list_item.add(ListViewModel("c","d"))
        list_item.add(ListViewModel("e","f"))

        val listview = findViewById<ListView>(R.id.mainListview)

        val listadapter = ListViewAdapter(list_item)

        listview.adapter = listadapter

activity_main.xml

activity_main.xml에서는 굳이 바꿔줄 필요가 없다.

listview_item.xml

listview_item.xml이 TextView 하나만 가지고 있어서, model의 2가지 변수를 모두 사용할 수 없으니 TextView를 하나 더 생성.

<TextView
        android:id="@+id/listviewItem"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

위 코드를 아래 코드처럼

    <TextView
        android:id="@+id/listviewItem"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/listviewItem2"
        android:textSize="20sp"
        android:layout_margin="5dp"
        android:text="리스트뷰 아이템2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

ListViewAdapter.kt

ListViewAdapter.kt에서는 getView()를 수정해서 model에 있는 title과 content를 모두 이용할 수 있도록 listview_item.xml의 TextView와 각각 연결 후, 각각 입력.

기존 코드

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var converView = convertView

        if(converView == null){
            converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
        }

        var title = converView!!.findViewById<TextView>(R.id.listviewItem)
        title.text = List[position]


        return converView!!
    }

수정 코드

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var converView = convertView

        if(converView == null){
            converView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
        }

        var title = converView!!.findViewById<TextView>(R.id.listviewItem)
        var content = converView!!.findViewById<TextView>(R.id.listviewItem2)
        title.text = List[position].title
        content.text = List[position].content


        return converView!!
    }
}

요약

어렵다.... 만들고 싶은 앱 있는데 만들 수 있을까 흑흑흑흑흑...

안드로이드 스튜디오에서 리스트를 사용하기 위해서는 adapter를 이용해줘야 하며, 리스트의 각 item이 어떻게 생겼는지도 보여줄 xml파일도 만들어줘야한다.

그리고, 리스트에 여러개의 값이 들어갈 것이라면, model파일을 만들어서 입력받을 리스트 값을 입력해주고, 위에 말한 adapter를 이용해주고, item이 어떻게 생겼는지 보여줄 xml파일도 만들어 주면된다.

쓰고나니 그리 어렵지 않은 것처럼 보이네..

할 수 있드아아아아아아아

profile
반드시 결승점을 통과하는 개발자

0개의 댓글