Android Kotlin基礎講座 06.3:Livedataを使ってボタンの状態をコントロールする
目次
タスク:ボタンの可視性のコントロールとスナックバーを追加する
ここまででアプリは十分に機能します。ユーザーはStartボタンとStopボタンを好きなだけタップすることができます。ユーザーがStopボタンをタップすると、睡眠の質を入力できるようになります。ユーザーがClearボタンをタップすると、全てのデータがバックグラウンドで静かに削除されます。
しかしながら、全てのボタンが常に有効でタップ可能です。これによってアプリが壊れることはありませんが、ユーザーが不完全な睡眠データを作り出してしまう可能性があります。
最後のこのタスクでは、transformation mapを使ってボタンの可視性をコントロールし、ユーザーが正しいタイミングでのみボタンを押せるようにする方法を学習します。また、同じようなメソッドを使って、全てのデータが削除されたあとに、メッセージを表示するようにしていきます。
ステップ1:ボタンの状態を更新する
ボタンの状態を設定することで、初めはStartボタンのみを有効にします。これはStartボタンのみがタップ可能であるということです。
ユーザーがStartボタンをタップしたあとは、Stopボタンが有効になり、Startボタンを無効にします。Clearボタンはデータがデータベースに存在するときにのみ有効になるようにします。
- fragment_sleep_tracker.xmlレイアウトファイルを開いてください。
- それぞれのボタンにandroid:enabledプロパティを追加してください。
android:enabledプロパティはボタンが有効か無効であるかを示すboolean値です。(有効なボタンはタップすることができ、無効なボタンはタップできません)
プロパティには状態を表す変数を渡してください。この変数はこの後定義します。
start_button
:
android:enabled="@{sleepTrackerViewModel.startButtonVisible}"
stop_button
:
android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"
clear_button
:
android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
- SleepTrackerViewModelを開き、対応する三つの変数を作成します。それぞれの変数にはit(tonightまたはnights)をチェックするtransformationを代入します。
- Startボタンはtonightがnullである場合に有効になるべきです。
- Stopボタンはtonightがnullでない場合に有効になるべきです。
- Clearボタンはnights、つまりデータベースにデータが含まれている場合のみ有効になるべきです。
val startButtonVisible = Transformations.map(tonight) {
it == null
}
val stopButtonVisible = Transformations.map(tonight) {
it != null
}
val clearButtonVisible = Transformations.map(nights) {
it?.isNotEmpty()
}
- アプリを起動し、ボタンを確かめてみてください。
Tip: 非表示ビューの見た目の設定
enabled属性はvisibility属性と同じではありません。
enabled属性はViewが有効かどうかのみを決めるのであって、Viewが見えるかどうかを決定するわけではありません。
“enabled(有効)”の意味はサブクラス(ビュー)ごとに異なります。ユーザーは有効なEditText内のテキストは編集できますが、無効なEditText内のテキストは編集できません。有効なボタンはタップできますが、無効なボタンはタップできません。
無効なViewには、そのViewがアクティブでないことを視覚的に表現するために、デフォルトのスタイルが適用されます。
しかしながら、Viewがbackground属性、またはtextColor属性を持っている場合、それらの属性の値はViewが非表示のときにも使われます。Viewが無効であった場合でもです。
Viewが有効なときと無効なときで使う色をそれぞれ定義したい場合は、テキストカラーにはColorStateList、背景色にはStateListDrawableを使ってください。
ステップ2:ユーザーに通知するためにスナックバーを使う
ユーザーがデータベースをクリアしたあとは、Snackbarウィジェットを使って確認メッセージを表示します。スナックバーは画面の下にメッセージを表示することで、簡潔なフィードバックを提供します。スナックバーはタイムアウトの後や、スクリーン上のどこか他でユーザー応答が発生した後、またはユーザーがスナックバーを画面外にスワイプした後に消えます。
スナックバーの表示はUIタスクで、フラグメント内で行われるべきです。スナックバーの表示の決定はViewModel内で行われます。データがクリアされた時にスナックバーをセットアップし、トリガーを引くためには、ナビゲーションのトリガーのときと同じ手法を使うことができます。
- SleepTrackerViewModel内で、カプセル化されたイベントを作成します。
private var _showSnackbarEvent = MutableLiveData<Boolean>()
val showSnackBarEvent: LiveData<Boolean>
get() = _showSnackbarEvent
- doneShowingSnackbar()を実装してください。
fun doneShowingSnackbar() {
_showSnackbarEvent.value = false
}
- SleepTrackerFragment内のonCreateView()にオブザーバーを追加してください。
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
- obeserverブロック内で、スナックバーの表示とイベントのリセットを行います。
if (it == true) { // Observed state is true.
Snackbar.make(
activity!!.findViewById(android.R.id.content),
getString(R.string.cleared_message),
Snackbar.LENGTH_SHORT // How long to display the message.
).show()
sleepTrackerViewModel.doneShowingSnackbar()
}
- SleepTrackerViewModel内、onClear()メソッドの中でイベントトリガーをオンにします。イベントの値をlaunchブロック内でtrueに設定してください。
_showSnackbarEvent.value = true
- ビルドしてアプリを起動してください。
完成済みプロジェクト
お疲れさまでした。完成済みプロジェクトは以下からダウンロードできます。