Contents
MainActivity에서 Adapter로 a,b,c란 데이터를 보낸다
그러면 Adapter에서 listview_item.xml에 a,b,c를 하나씩 값을 넣어서 activity_main.xml에 있는 listView에 넣어줌
구현하기
1. activity_main.xml에 mainListview라는 이름의 리스트뷰를 만든다
<ListView
android:id="@+id/mainListview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
이 리스트뷰에 아이템들(a,b,c)을 하나씩 넣어주어야 함.
하나씩 넣어주는 역할을 Adapter가 담당
MainActivity에서 Adapter로 데이터를 넣어주고 Adapter에서 데이터들을 하나하나 listview_item.xml에 넣어서 activity_main.xml에 있는 listview에 하나씩 넣어주어야 함
일단 MainActivity에서 Adapter로 데이터를 보내야하는데
Adapter가 지금 없으므로 Adapter를 생성하자
2. ListViewAdapter 생성
ListViewAdapter라는 이름의 코틀린 클래스 생성
class ListViewAdapter {
}
일단은 이 어댑터에서 ["a","b","c"] 같은 형태의 리스트 데이터를 받아줘야 한다
매개변수로 문자열 데이터들로 이루어진 리스트를 받는다
class ListViewAdapter(val List : MutableList<String>) {
}
BaseAdapter()를 상속받자
class ListViewAdapter(val List : MutableList<String>) : BaseAdapter() {
override fun getCount(): Int {
TODO("Not yet implemented")
}
override fun getItem(p0: Int): Any {
TODO("Not yet implemented")
}
override fun getItemId(p0: Int): Long {
TODO("Not yet implemented")
}
override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
TODO("Not yet implemented")
}
}
상속받은 메소드들
- getCount
- getItem
- getItemId
- getView
getCount
리스트뷰의 개수(item들의 개수)
item들의 개수는 매개변수로 받은 List의 크기만큼만 하겠다
override fun getCount(): Int {
return List.size
}
getItem
리스트에 아이템을 가져다 줌
override fun getItem(position: Int): Any {
return List[position]
}
getItemId
position을 반환
override fun getItemId(position: Int): Long {
return position.toLong()
}
getItem, getItemId는 특별히 신경쓰지 않아도 된다
getCount와 getView가 중요!!!
getView
getView에 리스트에 있는 아이템들을 하나씩 넣어주어야 함
(그림1) MainActivity에서 데이터를 받아와서 listview_item.xml에 하나씩 넣은 뒤 activity_main.xml 내에 있는 listview에 넣어줘야 함
getView 구현 전에 listview_item.xml을 생성하자
3. listview_item.xml 생성
layout > New > Layout Resource File
<?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>
이렇게 아이템이 만들어졌다
이제 이 아이템을 어댑터에 연결해주면 된다
연결시키는 방법은 ListViewAdapter로 와서 getView에서 연결해줌
매개변수에 있는 convertView를 이용해서 만들어줌
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var convertView = convertView
// listview_item.xml에 있는 뷰를 가져오는 부분
// ?는 널값을 가질수 있음을 의미
if (convertView == null) {
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
}
// !!는 널이 아님을 단언.
// 만약 convertView가 널이라면, NullPointException 발생
return convertView!!
}
이제 (그림1) MainActivity에 ["a","b","c"] 아이템들을 넣어주자
(그림1) MainActivity에서 Adapter로 데이터를 전달하고 Adapter에서 listview_item.xml으로 데이터들을 하나씩 넣어서 activity_main.xml에 있는 listview에 연결하는 순서로 가자
일단 데이터를 넘겨주는 것부터 해보자
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//문자열 데이터로 된 리스트
val list_item = mutableListOf<String>()
list_item.add("A")
list_item.add("B")
list_item.add("C")
//ListViewAdapter에 list_view 넣기
val adapter = ListViewAdapter(list_item)
}
}
이제 어댑터로 데이터가 전달이 되었다
(그림1) MainActivity에서 Adapter로 ["a","b","c"]가 전달이 되었고
이전 코드에서는 getView안에서 Adapter에서 listview_item.xml을 연결해놨다
이제 listview_item.xml을 activity_main.xml에 있는 listview와 연결해주자
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//문자열 데이터로 된 리스트
val list_item = mutableListOf<String>()
list_item.add("A")
list_item.add("B")
list_item.add("C")
// acivity_main.xml에 있는 ListView의 id 이름이 mainListview
val listview = findViewById<ListView>(R.id.mainListview)
//ListViewAdapter에 list_item("A","B","C") 넣기
val listAdapter = ListViewAdapter(list_item)
//listview의 adapter에 위에서 val로 선언한 listAdapter를 연결
listview.adapter = listAdapter
}
}
여기서
// ListViewAdapter에 list_item("A","B","C") 넣기
val listAdapter = ListViewAdapter(list_item)
// listview의 adapter로 listAdapter를 선언
listview.adapter = listAdapter
이 부분이 아래 그림에 해당
실행을 하면 다음과 같다
list_item 3개가 나왔음
여기서 드는 의문이 "A","B","C"가 나와야 하는데 listview_item.xml에 있는 "리스트뷰 아이템" 이 나와버렸다
"A","B","C" 가 나오도록 코드를 수정하자
(그림1) Adapter에서 받은 데이터들을 listview_item.xml에 하나씩 넣어주어야 한다
일단 ListViewAdapter로 이동
package com.asiae.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 convertView = convertView
if (convertView == null) {
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
}
// !!는 널이 아님을 단언.
// 만약 convertView가 널이라면, NullPointException 발생
return convertView!!
}
}
위의 코드에서
if (convertView == null) {
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
}
이 부분을 보면 convertView에 있는 것이 listview_item이다
MainActivity를 보면
A,B,C라는 값이 list_item에 담겨서 ListViewAdapter에 넣어졌다
val list_item = mutableListOf<String>()
list_item.add("A")
list_item.add("B")
list_item.add("C")
val listview = findViewById<ListView>(R.id.mainListView)
// list_item을 ListViewAdapter에 담음
val listAdapter = ListViewAdapter(list_item)
그래서 A,B,C라는 값이 ListViewAdapter의 매개변수인 List에 들어갔다
class ListViewAdapter(val List : MutableList<String>) : BaseAdapter()
그래서 이 A,B,C 값들을 하나씩 listview_item에 넣어주어야 함
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
어떻게 하면 listview_item에 A,B,C를 넣을 수 있을까?
convertView에 있는 listviewItem을 찾아 title이라고 지어준다
val title = convertView!!.findViewById<TextView>(R.id.listviewItem)
그리고 title에 있는 text를 ListViewAdapter의 매개변수인 List 각각의 아이템들로 연결
title.text = List[position]
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 convertView = convertView
if (convertView == null) {
convertView = LayoutInflater.from(parent?.context).inflate(R.layout.listview_item, parent, false)
}
val title = convertView!!.findViewById<TextView>(R.id.listviewItem)
//title에 있는 text를 ListViewAdapter의 매개변수인 List 각각의 아이템들로 연결
title.text = List[position]
// !!는 널이 아님을 단언.
// 만약 convertView가 널이라면, NullPointException 발생
return convertView!!
}
}
여기까지하고 listview를 실행시키자
A,B,C가 잘 나온것을 확인 가능
더 나아가기
MainActivity에 문자열 데이터가 아닌 데이터 모델을 전달해 줄 수도 있다
1. ListViewModel이라는 이름의 코틀린클래스 생성
* {}가 아닌 ()
data class ListViewModel (
var title : String = "",
var content: String = ""
)
값 두개가 있는 데이터 모델 생성
아래 그림과 같이 ListViewModel을 전달해보자
MainActivity를 다음과 같이 변경
val list_item = mutableListOf<ListViewModel>()
list_item.add(ListViewModel("a","b"))
list_item.add(ListViewModel("c","d"))
list_item.add(ListViewModel("e","f"))
그러면 다음과 같이 빨간줄이 뜬다
ListViewAdapter 부분도 수정을 해주어야 함
ListViewAdapter에서 매개변수 부분을 MutableList<ListViewModel>로 변경
class ListViewAdapter(val List : MutableList<ListViewModel>) : BaseAdapter() {
아래 코드도 다음과 같이 변경
title.text = List[position].title
// List[0] -> ListViewModel("a","b")
// List[1] -> ListViewModel("c","d")
// List[2] -> ListViewModel("e","f")
a,c,e 값을 잘 가져옴
아래와 같이 title을 content로 변경하면
title.text = List[position].content
// List[0] -> ListViewModel("a","b")
// List[1] -> ListViewModel("c","d")
// List[2] -> ListViewModel("e","f")
이렇게 나온다
title, content 두 개가 같이 나오게 하려면
listview_item에 TextView를 2개 만들면 된다
listview_item.xml로 가서 TextView 2개 생성
<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"/>
<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"/>
</LinearLayout>
listviewItem2를 가져와서 content부분에 넣자
ListViewAdapter로 돌아와 val title 아래 다음 코드를 넣는다
val content = convertView!!.findViewById<TextView>(R.id.listviewItem2)
그 아래 코드도 변경
title.text = List[position].title
content.text = List[position].content
실행시키면 각각의 아이템들이 잘 나온걸 확인 가능
완성코드는 listview_ex 폴더에서 확인 가능
리스트뷰 진짜 어렵다.... 여러 파일들이 생성되고 이 파일들이 모두 연결되는 부분들이 머릿속에서 잘 안그려져서 힘들었는데 recyclerView로 넘어가려면 확실히 알아두어야 할 내용이라서 여러번 보고 익숙해져야겠다...
'Android, Kotlin 📱 > [kotlin]앱 8개를 만들면서 배우는 안드로이드 코틀린' 카테고리의 다른 글
[kotlin]섹션 5-3 RecyclerView 만들어보기 (0) | 2023.10.27 |
---|