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ボタンが押せない状態にする
名前やエリアが未選択の場合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を
両方の値チェックでOKだった場合のみボタンを有効化しています。
combineLatest
で結合し、両方の値チェックでOKだった場合のみボタンを有効化しています。
name.isNotEmpty() && area != AdapterView.INVALID_POSITION
-> 名前が空でなく、spinnerの選択位置が空でない
オペレータ
- distinctUntilChanged連続して重複したデータを通知しないkotlin
disposable += Observable.fromArray(1, 2, 2, 3, 4, 5, 5, 6) .distinctUntilChanged() .subscribe(::println) // 1,2,3,4,5,6
- combineLatest
どちらか1つの送信される時、指定された関数によって、各Observableから送信される最新のアイテムを結合し、この関数の評価に基づいたアイテムを送信するkotlinval o1 = PublishSubject.create<Int>() val o2 = PublishSubject.create<String>() disposable += Observables.combineLatest( o1, o2 ) { n, s -> "${n}/${s}"} .subscribe(::println) o1.onNext(1) o2.onNext("a") o1.onNext(2) o1.onNext(3) o2.onNext("b") // 1/a // 2/a // 3/a // 3/b
バッドノウハウ
自分だけかもしれませんが、
(Observable(s)の違い)と書くとエラーになります。。
Observables.combineLatest
をObservable.combineLatest
(Observable(s)の違い)と書くとエラーになります。。
0 件のコメント:
コメントを投稿