wrongwrongな開発日記

情報系大学院生の忘備録

【Android】ListViewを使う【Kotlin】

自作クラスを使ったListViewの使い方をまとめます。この記事を書いた時点で用いているサンプルプロジェクトは以下。
github.com

やること

ListVIewを使うための準備は3つです。

  1. ListViewに表示するレイアウトを作る
  2. Adapterクラスを作る(アイテムの内容はここで設定)
  3. アクティビティへの配置とAdapterのセット(アイテムをタップした時の処理はここで設定)

最終的に、以下の画像のようなレイアウトの列挙が出来ます。
f:id:wrongwrongwrongwrong163377:20180815160611p:plain

表示するレイアウトを作る

レイアウトファイルを追加し、ListViewに表示するレイアウトを作ります。
この記事ではlanguage_item.xmlとしてTextViewを3つ水平に並べたものをサンプルとします。

<?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="match_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/num"
        android:layout_width="50sp"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:textSize="30sp"
        android:textColor="@color/colorWhite"
        android:gravity="center"
        android:shadowColor="@color/colorBlack"
        android:shadowRadius="10.0"
        android:text="99"/>

    <TextView
        android:id="@+id/language"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="5"
        android:textSize="30sp"
        android:text="language"/>

    <TextView
        android:id="@+id/parcent"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:textSize="30sp"
        android:gravity="right"
        android:text="nnn.nn%"/>
</LinearLayout>

Adapterクラスを作る

Adapterクラスは表示するItem全てを管理します。処理の流れとしては「コンストラクタに表示したいデータを渡して初期化→getViewで表示するViewを初期化」となります。
サンプルとしたLanguageAdapter(下記)では、getView内でアイテムに対応する文章や色を設定しています。

class LanguageAdapter(val context: Context,
                      val sortedList: List<Pair<String, Int>>,
                      numOfReps: Int,
                      val numColorIds: ArrayList<Int>) : BaseAdapter() {
    val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    var sumOfReps = numOfReps.toDouble()

    override fun getCount(): Int {
        return sortedList.count()
    }

    override fun getItem(position: Int): Pair<String, Int> {
        return sortedList[position]
    }

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

    @SuppressLint("ViewHolder", "SetTextI18n")
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val view = layoutInflater.inflate(R.layout.language_item, parent, false) //表示するレイアウト取得
        val numtext = view.findViewById<TextView>(R.id.num)
        numtext.text = "${sortedList[position].second}"
        numtext.background = ColorDrawable(ContextCompat.getColor(context, if(numColorIds[position] != 0) numColorIds[position] else R.color.colorWhite))

        view.findViewById<TextView>(R.id.language).text = sortedList[position].first
        view.findViewById<TextView>(R.id.parcent).text = "${String.format("%3.2f", ((sortedList[position].second * 100).toDouble() / sumOfReps))}%"
        return view
    }
}

アクティビティへの配置とAdapterのセット

ここまで作った内容を使うため、以下の3手順を行います。

  1. ListViewをレイアウトに配置
  2. ListViewにAdapterをセット
  3. ListViewにタップ時の挙動を設定
ListViewをレイアウトに配置

レイアウトに加えるだけです。

<!-- リストビュー配置 -->
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <!-- リストビュー配置 -->
</LinearLayout>
ListViewにAdapterをセット

以下のように、listViewにアダプターを入れるだけです。

val listView = findViewById(R.id.listView)
listView.adapter = LanguageAdapter(/* コンストラクタに必要な引数 */)
ListViewにタップ時の挙動を設定

setOnItemClickListenerでタップ時の挙動が設定できます。
positionにはタップされたアイテムの番号が入っており、例えばparent.getItemAtPosition(position)を呼び出すことでAdapterクラスに作成したgetItem(position: Int)を呼び出すことができます。

val listView = findViewById(R.id.listView)
listView.setOnItemClickListener{parent, v, position, id ->
    /* タップ時の挙動 */
}

ここまでの操作で自作クラスを使ったListViewが使えます。