2021年3月25日木曜日

ListViewに1件ずつ追加する方法

Androidでのリスト表示はListViewを使用することが多い。
何かを契機に1件ずつレコードを追加していく際によく以下のことが起こる
  • Listには追加できているのに見栄えに反映されない
  • 更新すると表示位置が先頭行に戻ってしまう
なので、
ボタンを押下を契機に一件ずつ要素を追加していき、
表示位置も維持するコードのサンプルを載せておく


サンプルコード

class MainActivity : AppCompatActivity() {
    private val adapter by lazy { ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mutableListOf()) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<ListView>(R.id.listView).adapter = adapter
    }

    /** ボタンが押された */
    fun onClick(v: View) {
        //押下時のタイムスタンプを追加していく
        adapter.add(LocalTime.now().toString())
    }
}


ちょっと解説

1件ずつ登録する処理はArrayAdapter#addをするだけでよい。
表示用のListを別途保持し更新を掛けたり、ListViewに対し描画更新要求は不要だ。
また、追加しても現在のスクロール位置が変わらず、追加するたびに先頭に戻される鬱陶しさもない。

設計アドバイス

「1件ずつ追加」のような、ListViewを何らかの契機でレコード数が変化するような場合に丁度よいAdapterはArrayAdapterだ。
Listを変化させ表示も更新してくれるメソッドがそろっている。
独自のカスタムレイアウトでListView作成を検討する際、どのAdapterをベースに継承させていくかの指標にすればよいかと。

まとめて複数件追加する場合はaddAllメソッド
削除する際もremoveメソッドが用意されている。

ListViewへ更新要求不要

プロローグでも述べたように、「Listに追加しても画面に反映されない」の原因は
ListViewの更新が必要なのに、更新要求ができていないパターンが多い。
例えばデータを更新した後にnotifyDataSetChangedが漏れていたり等
ArrayAdapter#addは、ListViewに更新要求せずに更新される。

現在のスクロール位置を維持

冒頭で述べた「更新すると表示位置が先頭行に戻ってしまう」について
ListViewの更新をアダプターを作り替えて再度setAdapterする実装のサンプルコードをよく見る。これをすると、ListViewの中身全部作り替えるのでListの先頭に戻させる。
現在表示位置を一時記録しておき、List更新後別メソッドで移動させたり、結構面倒なことを強いられる。
ArrayAdapterのメソッドを使えば位置を維持してくれるので制御が楽。


最後に

いつも通り、Java版のコードもGitに上げておく

0 件のコメント:

コメントを投稿