はじめに
Android の ListView の使い方を忘れてしまっていたので ListView の使い方についてまとめておきます(検索してもぱっとコードが出てこなかった。。。)。
ListView は一覧表示するときお世話になるのでこれさえ使えればわりと色々なアプリをつくれる気がします(iOS でいう UITableView だと思います)。
Cursor 系はよくわかってないので機会があればまた更新したいと思います。。。
ソース(github)ここをいい感じにしていきたい。
ListView
ListView の定義は下記です。
| 
					 1  | 
						open class ListView : AbsListView  | 
					
XML attributes で下記の値が設定できるようです。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						// 境界線(Drawable or color) android:divider // 境界線の高さ android:dividerHeight // リスト android:entries // false ならフッターの上の線を非表示にする(デフォtrue) android:footerDividersEnabled // false ならヘッダーの下の線を非表示にする(デフォtrue) android:headerDividersEnabled  | 
					
ListView 自体はどのような View を表示するという情報は持っておらず ListAdapter に対して表示する View を要求するみたいです(ListAdapter が UITableViewDataSourece + UITableViewCell 相当だと思います)。
つまり ListView で一覧表示したい場合はアダプター(ListAdapter)の設定が必須です。表示の更新とかもアダプターを介しておこないます。
アダプター
ListAdapter の定義は下記です。
| 
					 1  | 
						interface ListAdapter : Adapter  | 
					
ListAdapter を継承したクラスは下記 8 つが用意されているようです。
- ArrayAdapter
 - BaseAdapter
 - SimpleAdapter
 - WrapperListAdapter
 - HeaderViewListAdapter
 - CursorAdapter
 - ResourceCursorAdapter
 - SimpleCursorAdapter
 
ArrayAdapter
定義は下記です。
| 
					 1  | 
						open class ArrayAdapter<T : Any!> : BaseAdapter, Filterable, ThemedSpinnerAdapter  | 
					
1つのテキストを表示したい場合に使うようです。設定したリストのテキストが TextView に表示されます。下記のコンストラクタが用意されています。
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						<init>(context: Context, resource: Int) <init>(context: Context, resource: Int, textViewResourceId: Int) <init>(context: Context, resource: Int, objects: Array<T>) <init>(context: Context, resource: Int, textViewResourceId: Int, objects: Array<T>) <init>(context: Context, resource: Int, objects: MutableList<T>) <init>(context: Context, resource: Int, textViewResourceId: Int, objects: MutableList<T>)  | 
					
引数
- Context
何か適当なやつを。。。 - resource
レイアウトファイルの ID です(TextView 必須)。 - textViewResourceId
リストの項目を表示する TextView の id(レイアウトを自作するときに使う)。 - objects
表示するリストです。 
resource
レイアウトファイルの ID です。レイアウトファイルには少なくとも1つの TextView が必須です。
自作しなくても1つの TextView を表示するだけなら android.R.layout.simple_list_item_1 が用意されています。
こんな感じで使います。
| 
					 1 2 3  | 
						val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1) // 別にここでリスト設定してもいい listView.adapter = adapter adapter.add("AAA")  | 
					
textViewResourceId
リストの項目を表示する TextView の ID です。レイアウトを自作する場合に利用するものと思われます。
下記のようなレイアウトファイルを作成します。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						<?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:orientation="horizontal">     <TextView         android:id="@+id/text"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" /> </LinearLayout>  | 
					
下記のように設定するとリストが表示されました。
| 
					 1 2 3 4 5  | 
						val adapter = ArrayAdapter<String>(this, R.layout.text_row, R.id.text) // 別にここでリスト設定してもいい listView.adapter = adapter adapter.add("AAA") adapter.add("BBB") adapter.add("CCC")  | 
					
レイアウトファイルを修正すれば複数の View を置くことも可能です。ただし、可変で値を設定できるのは ID を指定している TextView のみです。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21  | 
						<?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="16dp"     android:orientation="horizontal">     <TextView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="タイトル:" />     <TextView         android:id="@+id/text"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" /> </LinearLayout>  | 
					
こんな感じ。

objects
表示する項目のリストです。Mutable ではない場合は Adapter の clear() や add() といったメソッドを使用したときにクラッシュしてしまいます。
型は String に変換できるなら何でもいいみたいです。試しに下記のように設定してみるとちゃんと表示されました。
| 
					 1 2 3 4 5 6 7 8  | 
						 data class Hoge(     val text: String,     val num: Int, ) listView.adapter = ArrayAdapter<Hoge>(this,             android.R.layout.simple_list_item_1,             listOf(Hoge("hoge", 1), Hoge("fuga", 2), Hoge("piyo", 3)))  | 
					
こんな感じです。

BaseAdapter
定義は下記です。
| 
					 1  | 
						abstract class BaseAdapter : ListAdapter, SpinnerAdapter  | 
					
カスタムアダプターを作るときに継承させるクラスです。これさえ使えればだいたいいける気がします。
使い方
レイアウトファイルと BaseAdapter を継承したカスタムクラスを用意します。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  | 
						<?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="16dp"     android:orientation="horizontal">     <CheckBox         android:id="@+id/checkBox"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:clickable="false"         android:focusable="false"         android:focusableInTouchMode="false" />     <TextView         android:id="@+id/text"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" /> </LinearLayout>  | 
					
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32  | 
						class CustomAdapter(context: Context,                     private val items: List<Hoge>) : BaseAdapter() {     private val inflater = LayoutInflater.from(context)     override fun getCount() = items.size     override fun getItem(position: Int) = items[position]     // 一覧内で一意になるやつ     override fun getItemId(position: Int) = position.toLong()     override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {         val view = convertView ?: createView(parent)         val item = getItem(position)         val viewHolder = view.tag as ViewHolder         viewHolder.text.text = item.text         viewHolder.checkBox.isChecked = item.num % 2 == 0         return view     }     private fun createView(parent: ViewGroup?): View {         val view = inflater.inflate(R.layout.custom_row, parent, false)         view.tag = ViewHolder(view)         return view     }     private class ViewHolder(view: View) {         val text = view.findViewById<TextView>(R.id.text)         val checkBox = view.findViewById<CheckBox>(R.id.checkBox)     } }  | 
					
ポイントは getView() の部分です。View の生成と findViewById はコストが高めなのでここを注意しないとスクロールがカクカクしてしまいます。convertView が null の場合のみView を生成し、毎回 findViewById をしないように生成時に ViewHolder で各 View を保持しておきます。
あとは ListView に設定するだけです。
| 
					 1 2 3 4 5 6  | 
						val adapter = CustomAdapter(     this,     listOf(Hoge("hoge", 1), Hoge("fuga", 2), Hoge("piyo", 3)) ) val listView = findViewById<ListView>(R.id.list) listView.adapter = adapter  | 
					
こんな感じ。

SimpleAdapter
定義は下記です。
| 
					 1  | 
						open class SimpleAdapter : BaseAdapter, Filterable, ThemedSpinnerAdapter  | 
					
Map の一覧を表示する場合に使うみたいです。表示はテキストのみです。
コンストラクタは下記が用意されています。
| 
					 1  | 
						<init>(context: Context!, data: MutableList<out MutableMap<String!, *>!>!, resource: Int, from: Array<String!>!, to: IntArray!)  | 
					
引数
- context
何か適当なやつを。。。 - data
表示するデータ。キーはfromに対応してる必要があります。 - resource
レイアウトファイルの ID です。 - from
表示したいデータのMapのキー一覧です。 - to
fromに対応したTextViewの ID 一覧です。 
使い方
レイアウトファイルを下記のように作成します。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28  | 
						<?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="16dp"     android:orientation="vertical">     <TextView         android:id="@+id/text1"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" />     <TextView         android:id="@+id/text2"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" />     <TextView         android:id="@+id/text3"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         tools:text="Text" /> </LinearLayout>  | 
					
ListView の設定は下記。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  | 
						val listView = findViewById<ListView>(R.id.list) val list = mutableListOf(     mutableMapOf(         "hoge" to Hoge("hoge1", 1),         "fuga" to Hoge("fuga1", 1),         "piyo" to Hoge("piyo1", 1)     ),     mutableMapOf(         "hoge" to Hoge("hoge2", 2),         "fuga" to Hoge("fuga2", 2),         "piyo" to Hoge("piyo2", 2)     ),     mutableMapOf(         "hoge" to Hoge("hoge3", 3),         "fuga" to Hoge("fuga3", 3),         "piyo" to Hoge("piyo3", 3)     ) ) val adapter = SimpleAdapter(this, list,     R.layout.simple_text_row,     arrayOf("hoge", "fuga", "piyo"),     arrayOf(R.id.text1, R.id.text2, R.id.text3).toIntArray() ) listView.adapter = adapter  | 
					
こんな感じです。

WrapperListAdapter
定義は下記です。
| 
					 1  | 
						interface WrapperListAdapter : ListAdapter  | 
					
アダプターをラップするアダプター?? getWrappedAdapter() で何をラップしてるか取得できるらしいですがイマイチ使い方はわかりません。。。
List adapter that wraps another list adapter. The wrapped adapter can be retrieved by calling getWrappedAdapter().
HeaderViewListAdapter
定義は下記です。
| 
					 1  | 
						open class HeaderViewListAdapter : WrapperListAdapter, Filterable  | 
					
ヘッダーがある ListView を扱う際に使われるらしい。。。(ちょっとよくわかってない)
おそらく addHeaderView(), addFooterView() とかでヘッダー・フッターを表示するとその Adapter が HeaderViewListAdapter でラップされるんだと思われます。
getHeadersCount() などのメソッドが用意されているのでヘッダー・フッターを操作したいときに使うのかも??
ListAdapter used when a ListView has header views. This ListAdapter wraps another one and also keeps track of the header views and their associated data objects.
This is intended as a base class; you will probably not need to use this class directly in your own code.
CursorAdapter
定義は下記です。
| 
					 1  | 
						abstract class CursorAdapter : BaseAdapter, Filterable, ThemedSpinnerAdapter  | 
					
DB で扱う Cursor を扱う用のアダプター。たぶん大量にデータを扱う際に使う??(ちょっとわからない。。。)
CursorAdapter を継承したカスタムクラスを作って使う??
下記2つのメソッドで表示処理を行うんだと思われます。
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						abstract fun bindView(     view: View!,      context: Context!,      cursor: Cursor! ): Unit abstract fun newView(     context: Context!,      cursor: Cursor!,      parent: ViewGroup! ): View!  | 
					
コンストラクタは下記2つが用意されている模様。
| 
					 1 2 3  | 
						<init>(context: Context!, c: Cursor!, autoRequery: Boolean) <init>(context: Context!, c: Cursor!, flags: Int)  | 
					
引数
- context
何か適当なやつを。。。 - c
表示するデータ。 - autoRequery
trueにすると常に最新のデータを DB から取って表示してくれるらしい(けどtrueにはしない方がいいらしい??)。 - flags
アダプタの動作を決定するために使用されるフラグ??(FLAG_AUTO_REQUERY,FLAG_REGISTER_CONTENT_OBSERVER) 
ResourceCursorAdapter
定義は下記です。
| 
					 1  | 
						abstract class ResourceCursorAdapter : CursorAdapter  | 
					
コンストラクタは下記2つが用意されている模様。
| 
					 1 2 3  | 
						<init>(context: Context!, layout: Int, c: Cursor!, autoRequery: Boolean) <init>(context: Context!, layout: Int, c: Cursor!, flags: Int)  | 
					
引数
下記以外は CursorAdapter と同様。
- layout
レイアウトファイルの ID です。 
CursorAdapter で必要な View をレイアウトファイルで指定して使うんだと思います(よくわかってない。。。 CusorAdapter でカスタムしたい場合は基本こいつを継承させるのかも??)。
SimpleCursorAdapter
定義は下記です。
| 
					 1  | 
						open class SimpleCursorAdapter : ResourceCursorAdapter  | 
					
テキスト表示だけの場合に使うのかも??
用意されているコンストラクタは下記1つの模様。
| 
					 1  | 
						<init>(context: Context!, layout: Int, c: Cursor!, from: Array<String!>!, to: IntArray!, flags: Int)  | 
					
引数
下記以外は ResourceCursorAdapter と同様。
- from
表示したいデータの DB のカラム名一覧です。 - to
fromに対応したTextViewの ID 一覧です。 
ヘッダー・フッター
ListView には下記メソッドが用意されており、これでヘッダー・フッターを表示するようです。
| 
					 1 2 3 4 5  | 
						addFooterView(v: View!, data: Any!, isSelectable: Boolean) addFooterView(v: View!) addHeaderView(v: View!, data: Any!, isSelectable: Boolean) addHeaderView(v: View!)  | 
					
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50  | 
						val listView = findViewById<ListView>(R.id.list) val adapter = ArrayAdapter(     this,     android.R.layout.simple_list_item_1,     mutableListOf(Hoge("hoge", 1), Hoge("fuga", 2), Hoge("piyo", 3)) ) listView.adapter = adapter val header1 = TextView(this).apply {     this.layoutParams = LinearLayout.LayoutParams(         ViewGroup.LayoutParams.MATCH_PARENT,         100     )     this.setBackgroundColor(getColor(R.color.purple_200))     this.setTextColor(getColor(R.color.white))     this.text = "Header1" } listView.addHeaderView(header1) val header2 = TextView(this).apply {     this.layoutParams = LinearLayout.LayoutParams(         ViewGroup.LayoutParams.MATCH_PARENT,         100     )     this.setBackgroundColor(getColor(R.color.purple_500))     this.setTextColor(getColor(R.color.white))     this.text = "Header2" } listView.addHeaderView(header2) val footer1 = TextView(this).apply {     this.layoutParams = LinearLayout.LayoutParams(         ViewGroup.LayoutParams.MATCH_PARENT,         100     )     this.setBackgroundColor(getColor(R.color.purple_200))     this.setTextColor(getColor(R.color.white))     this.text = "Footer1" } listView.addFooterView(footer1) val footer2 = TextView(this).apply {     this.layoutParams = LinearLayout.LayoutParams(         ViewGroup.LayoutParams.MATCH_PARENT,         100     )     this.setBackgroundColor(getColor(R.color.purple_500))     this.setTextColor(getColor(R.color.white))     this.text = "Footer2" } listView.addFooterView(footer2)  | 
					
上記のように設定するとこんな感じになりました。

ヘッダー・フッターは複数設定できるようです。KITKAT 以前は Adapter 設定前に add() する必要があったようですが今はどこでもいいみたいです。
おわりに
これで一覧表示がだいたいできるようになりました!
セクション表示とかもっと色々やりたい場合は RecyclerView を使うみたいです(ちょっとだけ設定がめんどくさい)。
For a more modern, flexible, and performant approach to displaying lists, use android.support.v7.widget.RecyclerView.
参考
- Androidのお勉強 第二回 ListViewと独自Adapterについて
 - [Android] ListViewアイテムの移動、削除
 - ListView
 - ListAdapter
 - ArrayAdapter
 - BaseAdapter
 - WrapperListAdapter
 - CursorAdapter
 - HeaderViewListAdapter
 - ResourceCursorAdapter
 - SimpleAdapter
 - SimpleCursorAdapter
 
  
  
  
  
コメント