個人事業とWebアプリ案件もやってます。read最近Kotlinに色んな意味でハマっているんですが、その中でも一番ハマったListViewにEditTextとButtonを配置したときの実装について、備忘録を載せたいと思います。いうのも、おそらくこの実装にチャレンジした人はわかって頂けると思うのですが、様々な落とし穴があります。ListViewにButtonを含むとOnItemClickListenerと競合するEditTextを変更してもListView側のリストに反映されないAddTextChangedListenerを設定すると、入力するたびにフォーカスが外れるなどなど、細かいものを挙げればキリがないのですが、今回はこれらの問題をおおよそ解決出来るような実装を紹介します。いやあ、ListView(Adapter)の闇は深い。1.0.4DataBindingサンプルは、ダイアログ上に編集可能なリストを表示するアプリです。雰囲気は以下のような感じ。ダイアログの実装まで書くと長くなるため、Adapter側の実装をメインに書きます。Button)を持つアダプタ。今回はこのアダプタをダイアログ上で表示する。</RelativeLayout></layout>画面上に表示していないpositionを取るTextViewが存在するが、これがミソ。ちなみに型をIntで取ろうとしたら、XMLは文字だけじゃコラと怒られてしまう(自分だけ?)。表示しないpositionの値をここで書くのは、後述のバインディングの際に値を保持するためで、xml上の何処かで使用していないとコンパイル時に最適化されて(?)エラーが出るため。}}Adapterのitemsはprivateのため、直接いじるにはちょっと面倒。そのため、初期化で新しいitemsをMutableListで保持し、これを元にAdapterの値を変更していこうという発想。...getView内の実装はよくある感じになっている。気を付けたいのは、getViewは初期化の際や更新時に何度も呼ばれるため、addTextChangedListenerは上記のタイミングで設定するようにしないと、重複して何度も登録されてしまうという現象が起こって大変なことになる。getItem(position)contentへのバインディングはよく知られている通り。positionへの設定は少しテクニカルかもしれない。これはEditTextを用いる上で重要な設定で、色々試行錯誤した結果、ここに設定して保持するのがスマートかと感じた。reload()}ListItemの追加・削除ボタンにリスナーを登録。後述のreload()で更新を反映。notifyDataSetChanged()}Viewへの反映としてreload()を用意している。これは、現在のitemsの状態をAdapterのitemsに反映させる。{}}この内部クラスではBindingを引数に取って保持することで、EditTextの編集文字列とitemsの対応を可能にする。binding.contentで現在のListItemの値が取得可能なら、同じように設定すればbinding.positionも取得可能なはずだ。onTextChangeで変更直後に即座にitemsに反映という実装はよく紹介されているが、それらのレイでは直接Adapter#insert,addなどを用いて操作するため、フォーカスが外れるという現象が起こってしまう。そこで、入力文字列の変更に関しては、CustomAdapterのitemsプロパティへの反映までで留めておき、ListItemの追加・削除か、画面を抜けたときに明示的に呼ぶreload()のタイミングでAdapterに反映させれば良いと考えた。CharSequenceに編集前の古い値が入ってきて上書きされるという現象が起こってしまっていた。そのためsizeをプロパティとして持ち、ListItem数の変更の際はこれを飛ばす処理のために用いている。ContentDialogFragmentダイアログはDialogFragmentを用いる。以下のように設定すれば良いと思う。</LinearLayout></layout>emptyListは参考までに。}}onCreateDialogに関してはまあこんな雰囲気という感じ。今回のダイアログは別のActivityから呼ばれることを想定しているため、先のCustomAdapterの変更を通知するためのnotifyDataSetChanged()を設定し、その中でCustomAdapter#reloadとCustomAdapter#notifyDataSetChangedを呼ぶ。reloadを呼ばないと、CustomAdapter#itemsの最終状態がAdapter#itemsに反映されない。後はOKボタンが押されたらデータを保存する処理を書けば良い。まとめListViewでEditTextやButtonを使う実装は中々難しいのか、有用な情報があまりなかったのですが、今回やっと思った通りの動きが実現できたので良かったです。良い実装はまだあるかと思うので、知ってる方がいれば是非教えていただきたいと思います。Part3さてさて久しぶり(?)の洋楽紹介コーナーです。これまでクラブミュージックの中でもノリの良い曲を紹介してきましたが、今回はちょっとシックなメロディの、私が一押しする曲をいくつか紹介したいと思います。APIが公開されました。