【Android】ExpandableListViewの使い方

Kotlinが公式になったというので5, 6年ぶりにAndroid再入門。

kogoto.hatenablog.com

想定するデータセット

親子関係のデータ。ここではこんなんを想定しています。

folders

id name
1 fodler1
2 fodler2
3 fodler3

categories

id folder_id name
1 1 category1
2 1 category2
3 1 category3
4 2 category1
5 2 category2
6 2 category3

実装概要

データセットのマップリストとかマップのマップリストとか用意してアダプタに差し込みます。
この辺りを書くのがJavaだと冗長でつらたんですがKotlinはvalで宣言できるしnewもいらんのですね。

// java
List<Map<String, String>> folders = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> categoriesOfFolder = new ArrayList<List<Map<String, String>>>();
// kotlin
val folders = mutableListOf<Map<String, String>>()
val categoriesOfFolder = mutableListOf<MutableList<Map<String, String>>>()

このリストをアダプタに設定します。引数はリファレンス見てください。

SimpleExpandableListAdapter | Android Developers

val adapter = SimpleExpandableListAdapter(
        this,
        folders,
        android.R.layout.simple_expandable_list_item_1,
        arrayOf(KEY_PARENT),
        intArrayOf(android.R.id.text1, android.R.id.text2),
        categoriesOfFolder,
        android.R.layout.simple_expandable_list_item_1,
        arrayOf(KEY_CHILD),
        intArrayOf(android.R.id.text1, android.R.id.text2)
)

リストのイベントは

  • OnGroupClickListener
  • OnChildClickListener
  • OnGroupExpandListener
  • OnGroupCollapseListener

などで拾ってください。

画面イメージ

f:id:ktdk:20170627230103p:plain

このままだとリストが開いているのか閉じているのか分かりにくいので、開閉しているステートを取ってビューの色変えたりしたいですよね。ListenerでもいけそうだけどAdapterカスタマイズして書くのがスマートだった気がします。そこはまたの機会に。

ソースコード

package com.example

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ExpandableListView
import android.widget.SimpleExpandableListAdapter

class MainActivity : AppCompatActivity() {

    companion object {
        const val KEY_PARENT = "FOLDER"
        const val KEY_CHILD = "CATEGORY"
    }

    private lateinit var mAdapter: SimpleExpandableListAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        loadFolders()
    }

    private fun loadFolders() {
        val folders = mutableListOf<Map<String, String>>()
        val categoriesOfFolder = mutableListOf<MutableList<Map<String, String>>>()

        for (i in 1..5) {
            val category = mapOf(KEY_PARENT to KEY_PARENT + i.toString())
            folders.add(category)

            val categories = mutableListOf<Map<String, String>>()

            for (j in 1..3) {
                val todo = mapOf(KEY_CHILD to KEY_CHILD + j.toString())
                categories.add(todo)
            }

            categoriesOfFolder.add(categories)
        }

        mAdapter = SimpleExpandableListAdapter(
                this,
                folders,
                android.R.layout.simple_expandable_list_item_1,
                arrayOf(KEY_PARENT),
                intArrayOf(android.R.id.text1, android.R.id.text2),
                categoriesOfFolder,
                android.R.layout.simple_expandable_list_item_1,
                arrayOf(KEY_CHILD),
                intArrayOf(android.R.id.text1, android.R.id.text2)
        )

        val listView = (findViewById(R.id.todoListView) as ExpandableListView)
        listView.setAdapter(mAdapter)
    }
}

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング