From 8601d2331409882da6f3eacdd17977237580f1b4 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 2 Aug 2020 02:05:55 +0700 Subject: [PATCH] update logic --- .../widget/BaseVisualControl.kt | 70 +++++++++++-------- .../reactiveviewmodel/widget/CheckControl.kt | 11 ++- .../reactiveviewmodel/widget/InputControl.kt | 70 +++++++++---------- .../reactiveviewmodel/widget/RatingControl.kt | 25 +++---- 4 files changed, 88 insertions(+), 88 deletions(-) diff --git a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/BaseVisualControl.kt b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/BaseVisualControl.kt index 8897dfa..b3dc80c 100644 --- a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/BaseVisualControl.kt +++ b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/BaseVisualControl.kt @@ -2,12 +2,16 @@ package com.alexdeww.reactiveviewmodel.widget import android.view.View import androidx.annotation.CallSuper +import com.alexdeww.reactiveviewmodel.core.property.State import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.BackpressureStrategy +import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable +typealias OnVisibleChangeAction = (isVisible: Boolean) -> Unit + abstract class BaseVisualControl( initialValue: T ) : BaseControl() { @@ -18,42 +22,48 @@ abstract class BaseVisualControl( val actionChangeValue = action() - protected open fun transformObservable(observable: Observable): Observable = observable - - @CallSuper - protected open fun onChangedValue(newValue: T) { - value.consumer.accept(newValue) - } - init { actionChangeValue .observable .filter { it != value.value } .let { transformObservable(it) } + .filter { it != value.value } .subscribe(::onChangedValue) } -} + fun State.toViewFlowable(): Flowable = this + .observable + .toFlowable(BackpressureStrategy.LATEST) + .observeOn(AndroidSchedulers.mainThread()) -internal fun BaseVisualControl.commonBindTo( - view: View, - invisibleState: Int -): Disposable = CompositeDisposable().apply { - add( - isEnabled - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) - .filter { it != view.isEnabled } - .subscribe { view.isEnabled = it } - ) - - add( - isVisible - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) - .filter { it != (view.visibility == View.VISIBLE) } - .subscribe { view.visibility = if (it) View.VISIBLE else invisibleState } - ) -} \ No newline at end of file + fun defaultBindTo( + view: View, + invisibleState: Int = View.GONE, + onVisibleChange: OnVisibleChangeAction? = null + ): Disposable = CompositeDisposable().apply { + add( + isEnabled + .toViewFlowable() + .subscribe { view.isEnabled = it } + ) + + add( + isVisible + .toViewFlowable() + .subscribe { + when { + onVisibleChange != null -> onVisibleChange.invoke(it) + else -> view.visibility = if (it) View.VISIBLE else invisibleState + } + } + ) + } + + protected open fun transformObservable(observable: Observable): Observable = observable + + @CallSuper + protected open fun onChangedValue(newValue: T) { + value.consumer.accept(newValue) + } + +} diff --git a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/CheckControl.kt b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/CheckControl.kt index 1a5ff42..3988a9e 100644 --- a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/CheckControl.kt +++ b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/CheckControl.kt @@ -3,8 +3,6 @@ package com.alexdeww.reactiveviewmodel.widget import android.annotation.SuppressLint import android.view.View import android.widget.CompoundButton -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable @@ -18,16 +16,15 @@ fun checkControl(initialChecked: Boolean = false): CheckControl = CheckControl(i fun CheckControl.bindTo( compoundButton: CompoundButton, - invisibleState: Int = View.GONE + invisibleState: Int = View.GONE, + onVisibleChange: OnVisibleChangeAction? = null ): Disposable { var editing = false return CompositeDisposable().apply { - add(commonBindTo(compoundButton, invisibleState)) + add(defaultBindTo(compoundButton, invisibleState, onVisibleChange)) add( value - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) + .toViewFlowable() .subscribe { editing = true compoundButton.isChecked = it diff --git a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/InputControl.kt b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/InputControl.kt index acb6d64..80ad102 100644 --- a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/InputControl.kt +++ b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/InputControl.kt @@ -40,45 +40,18 @@ fun inputControl( formatter: FormatterAction? = null ): InputControl = InputControl(initialText, hideErrorOnUserInput, formatter) - -private val EditText.textChanges: Observable - get() = Observable - .create { emitter -> - val listener = object : TextWatcher { - override fun afterTextChanged(s: Editable?) { - /* nothing */ - } - - override fun beforeTextChanged( - s: CharSequence?, - start: Int, - count: Int, - after: Int - ) { - /* nothing */ - } - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - if (s != null) emitter.onNext(s) - } - } - addTextChangedListener(listener) - emitter.setCancellable { removeTextChangedListener(listener) } - } - fun InputControl.bindTo( editText: EditText, useError: Boolean = false, - invisibleState: Int = View.GONE + invisibleState: Int = View.GONE, + onVisibleChange: OnVisibleChangeAction? = null ): Disposable { var editing = false return CompositeDisposable().apply { - add(commonBindTo(editText, invisibleState)) + add(defaultBindTo(editText, invisibleState, onVisibleChange)) add( value - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) + .toViewFlowable() .subscribe { val editable = editText.text if (!it!!.contentEquals(editable)) { @@ -98,9 +71,7 @@ fun InputControl.bindTo( if (useError) { add( error - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) + .toViewFlowable() .subscribe { s -> editText.error = s.takeIf { it.isNotEmpty() } } ) } @@ -118,9 +89,10 @@ fun InputControl.bindTo( fun InputControl.bindTo( textInputLayout: TextInputLayout, useError: Boolean = false, - invisibleState: Int = View.GONE + invisibleState: Int = View.GONE, + onVisibleChange: OnVisibleChangeAction? = null ): Disposable = CompositeDisposable().apply { - add(bindTo(textInputLayout.editText!!, false, invisibleState)) + add(bindTo(textInputLayout.editText!!, false, invisibleState, onVisibleChange)) if (useError) { add( error @@ -130,4 +102,28 @@ fun InputControl.bindTo( .subscribe { s -> textInputLayout.error = s.takeIf { it.isNotEmpty() } } ) } -} \ No newline at end of file +} + +private val EditText.textChanges: Observable + get() = Observable.create { emitter -> + val listener = object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + /* nothing */ + } + + override fun beforeTextChanged( + s: CharSequence?, + start: Int, + count: Int, + after: Int + ) { + /* nothing */ + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + if (s != null) emitter.onNext(s) + } + } + addTextChangedListener(listener) + emitter.setCancellable { removeTextChangedListener(listener) } + } diff --git a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/RatingControl.kt b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/RatingControl.kt index c53c96f..c5a1bfe 100644 --- a/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/RatingControl.kt +++ b/reactiveviewmodel/src/main/java/com/alexdeww/reactiveviewmodel/widget/RatingControl.kt @@ -3,8 +3,6 @@ package com.alexdeww.reactiveviewmodel.widget import android.annotation.SuppressLint import android.view.View import android.widget.RatingBar -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Observable import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.Disposable @@ -16,24 +14,17 @@ class RatingControl internal constructor( fun ratingControl(initialValue: Float = 0f): RatingControl = RatingControl(initialValue) -private val RatingBar.ratingBarChange: Observable - get() = Observable.create { emitter -> - setOnRatingBarChangeListener { _, rating, _ -> emitter.onNext(rating) } - emitter.setCancellable { onRatingBarChangeListener = null } - } - fun RatingControl.bindTo( ratingBar: RatingBar, - invisibleState: Int = View.GONE + invisibleState: Int = View.GONE, + onVisibleChange: OnVisibleChangeAction? = null ): Disposable { var editing = false return CompositeDisposable().apply { - add(commonBindTo(ratingBar, invisibleState)) + add(defaultBindTo(ratingBar, invisibleState, onVisibleChange)) add( value - .observable - .toFlowable(BackpressureStrategy.LATEST) - .observeOn(AndroidSchedulers.mainThread()) + .toViewFlowable() .subscribe { editing = true ratingBar.rating = it @@ -48,4 +39,10 @@ fun RatingControl.bindTo( .subscribe(actionChangeValue.consumer) ) } -} \ No newline at end of file +} + +private val RatingBar.ratingBarChange: Observable + get() = Observable.create { emitter -> + setOnRatingBarChangeListener { _, rating, _ -> emitter.onNext(rating) } + emitter.setCancellable { onRatingBarChangeListener = null } + }