ListView는 사용자가 정의한 데이터 목록을 세로 방향으로 나열하여 화면에 표시하는 뷰 그룹의 한 종류이며 Adapter로부터 생성 된 뷰를 받아 리스트뷰의 항목으로 배치한다.
💡 ListView는 리스트 항목이 갱신될 때마다 아이템 뷰를 새로 구성해야 하는 단점이 있으며 스크롤 과정에서 Memory Inflate가 발생하고 속도가 저하되는 등의 문제가 발생한다.
이러한 단점을 보완한 게 뷰 그룹의 한 종류인 RecyclerView이다. 안드로이드에서는 RecyclerView의 사용을 권장하고 있다.
Adapter는 보여지는 리스트뷰와 뷰에 올릴 데이터를 연결하는 다리 역할을 하며 ListView에 사용자가 정의한 데이터를 표시하기 위해서는 Adapter를 사용해야 한다.
// activity_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<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=".activity.ListViewActivity">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#00000000"
android:dividerHeight="3dp" />
</LinearLayout>
</layout>
// ListViewModel.kt
data class ListViewModel(
val image: Drawable, val title: String, val content: String
)
// item_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<ImageView
android:id="@+id/imageArea"
android:layout_width="80dp"
android:layout_height="80dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/titleArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="center_vertical"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/contentArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:textColor="@color/black"
android:textSize="12sp" />
<TextView
android:id="@+id/priceArea"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:textColor="@color/black"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
class ListViewAdapter(val items: MutableList<ListViewModel>) : BaseAdapter() {
// 리스트의 전체 크기를 반환하는 메서드
override fun getCount(): Int {
return items.size
}
// 해당 위치의 Item을 반환하는 메서드
override fun getItem(position: Int): Any {
return items[position]
}
// 해당 위치의 Item Id를 반환하는 메서드
override fun getItemId(position: Int): Long {
return position.toLong()
}
// .xml 파일의 View와 데이터를 연결하는 중요한 역할의 메서드
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
// LayoutInflater : item을 Adapter에서 View로 부풀려주는 역할
var view = convertView
if (view == null) view =
LayoutInflater.from(parent?.context).inflate(R.layout.item_listview, parent, false)
val image = view?.findViewById<ImageView>(R.id.imageArea)
val title = view?.findViewById<TextView>(R.id.titleArea)
val content = view?.findViewById<TextView>(R.id.contentArea)
val price = view?.findViewById<TextView>(R.id.priceArea)
image!!.setImageResource(items[position].image)
title!!.text = items[position].title
content!!.text = items[position].content
price!!.text = items[position].price
// view 반환
return view!!
}
}
// ListViewActivity.kt
class ListViewActivity : AppCompatActivity() {
private lateinit var binding: ActivityListViewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_list_view)
initListView()
}
fun initListView() {
val itemList = mutableListOf<ListViewModel>()
itemList.add(ListViewModel(R.drawable.item_lv_01, "마리떼 프랑소와 저버", "CLASSIC LOGO CAP beige", "49,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_02, "마리떼 프랑소와 저버", "CLASSIC LOGO WOOL ECO BAG blue", "49,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_03, "마리떼 프랑소와 저버", "COLOR BLOCK SATIN SCRUNCHIE navy", "39,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_04, "마리떼 프랑소와 저버", "CLASSIC LOGO BACKPACK light blue", "159,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_05, "마리떼 프랑소와 저버", "CLASSIC LOGO COLOR BEANIE navy", "49,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_06, "원브릴리언트", "Ivan-OB166-Black", "112,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_07, "시엔느", "Washing Lettering Ball Cap (Navy)", "49,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_08, "마뗑킴", "ACCORDION WALLET IN WHITE", "88,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_09, "마리떼 프랑소와 저버", "CIRCLE LOGO SATIN HAIRBAND ivorye", "29,000원"))
itemList.add(ListViewModel(R.drawable.item_lv_10, "리엔느와르","Dot Toggle Pearl Necklace (2color)", "57,000원"))
val adapter = ListViewAdapter(itemList)
// Adapter를 ListView 연결한다.
binding.listView.adapter = adapter
}
}
}
binding.listView.onItemClickListener =
AdapterView.OnItemClickListener { parent, view, position, id ->
val item = parent.getItemAtPosition(position) as ListViewModel
Toast.makeText(this, item.title, Toast.LENGTH_SHORT).show()