RxBinding
AndroidのUIコンポーネントをRx~でよろしく触れるようにしたもの
環境構築
今回はKotlinを使うのでRxBindingもKotlin用をインストール
app/build.gradle
// RxKotlin
compile "io.reactivex.rxjava2:rxkotlin:$rxkotlin_version"
// RxBinding
compile "com.jakewharton.rxbinding2:rxbinding-kotlin:$rxbinding_version"
実装
簡単なサンプル
よくある以下のようなフォーム画面を作成してみる。
- 入力フィールドに正しい値が設定されている時のみSubmitボタンが押せるようにする
レイアウトはこんな感じ
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/profileToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:theme="@style/ToolbarTheme"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
app:errorEnabled="true"
app:hintEnabled="true"
app:hintAnimationEnabled="true">
<EditText
android:id="@+id/profileName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:maxLength="20"
android:inputType="text"
android:hint="@string/hint_name" />
</android.support.design.widget.TextInputLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hint_area"/>
<Spinner
android:id="@+id/spinnerArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:entries="@array/areas" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:paddingStart="50dp"
android:paddingEnd="50dp"
android:gravity="center">
<Button
android:id="@+id/profileSubmit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/round_shape_disabled"
android:enabled="false"
android:text="@string/save"
android:textColor="@android:color/white"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

名前とエリアを選択するフォーム画面
名前やエリアが未選択の場合Submitボタンが押せない状態にする
kotlin
val nameChanges = profileName.textChanges()
val areaChanges = spinnerArea.itemSelections()
disposable += Observables.combineLatest(nameChanges, areaChanges)
{name, area -> name.isNotEmpty() && area != AdapterView.INVALID_POSITION}
.subscribe { isValid ->
profileSubmit.isEnabled = isValid
profileSubmit.setBackgroundResource(
if (isValid)
R.drawable.round_shape_enabled
else
R.drawable.round_shape_disabled)
}
名前とエリアのObservableをcombineLatest
で結合し、
両方の値チェックでOKだった場合のみボタンを有効化しています。
name.isNotEmpty() && area != AdapterView.INVALID_POSITION
-> 名前が空でなく、spinnerの選択位置が空でない
オペレータ
バッドノウハウ
自分だけかもしれませんが、Observables.combineLatest
をObservable.combineLatest
(Observable(s)の違い)と書くとエラーになります。。