何かを契機に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 件のコメント:
コメントを投稿