2021年3月25日木曜日

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

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


サンプルコード

  1. class MainActivity : AppCompatActivity() {
  2. private val adapter by lazy { ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mutableListOf()) }
  3.  
  4. override fun onCreate(savedInstanceState: Bundle?) {
  5. super.onCreate(savedInstanceState)
  6. setContentView(R.layout.activity_main)
  7. findViewById<ListView>(R.id.listView).adapter = adapter
  8. }
  9.  
  10. /** ボタンが押された */
  11. fun onClick(v: View) {
  12. //押下時のタイムスタンプを追加していく
  13. adapter.add(LocalTime.now().toString())
  14. }
  15. }


ちょっと解説

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 件のコメント:

コメントを投稿