@@ -18,7 +18,6 @@ import io.reactivex.Flowable
1818import io.reactivex.disposables.CompositeDisposable
1919import io.reactivex.functions.Consumer
2020import io.reactivex.internal.functions.Functions
21- import io.reactivex.processors.FlowableProcessor
2221import io.reactivex.processors.PublishProcessor
2322import io.reactivex.schedulers.Schedulers
2423import java.util.concurrent.TimeUnit
@@ -29,37 +28,42 @@ class ValidatableTextInputLayout @JvmOverloads constructor(
2928 defStyleAttr : Int = 0
3029) : TextInputLayout(context, attrs, defStyleAttr), ValidatableView {
3130
32- override val validationFlowables: ArrayList <Flowable <Any >> = ArrayList ()
31+ override val validationFlowables = ArrayList <Flowable <Any >>()
3332
3433 companion object {
34+ private val NONE = - 1
3535 private val FOCUS_CHANGED = 1
3636 private val TEXT_CHANGED = 1 shl 1
3737 }
3838
39- private var shouldValidateOnFocusChanged: Boolean = false
40- private var shouldValidateOnTextChanged: Boolean = false
41- private var shouldValidateOnTextChangedOnce: Boolean = false
42- private var validationInterval: Long = 300L
39+ private var shouldValidateOnFocusChanged = false
40+ private var shouldValidateOnTextChanged = false
41+ private var shouldValidateOnTextChangedOnce = false
42+ private var triggerAfterValidation = false
43+ private var validationInterval = 300L
4344
4445 init {
4546 val a = context.theme.obtainStyledAttributes(attrs, R .styleable.ValidatableTextInputLayout , 0 , 0 )
4647
47- val trigger = a.getInt(R .styleable.ValidatableTextInputLayout_trigger , FOCUS_CHANGED )
48- shouldValidateOnFocusChanged = trigger and FOCUS_CHANGED != 0
49- shouldValidateOnTextChanged = trigger and TEXT_CHANGED != 0
48+ val trigger = a.getInt(R .styleable.ValidatableTextInputLayout_trigger , NONE )
49+ if (trigger > 0 ) {
50+ shouldValidateOnFocusChanged = trigger and FOCUS_CHANGED != 0
51+ shouldValidateOnTextChanged = trigger and TEXT_CHANGED != 0
52+ }
5053
54+ triggerAfterValidation = a.getBoolean(R .styleable.ValidatableTextInputLayout_triggerAfterValidation , false )
5155 validationInterval = a.getInteger(R .styleable.ValidatableTextInputLayout_interval , 300 ).toLong()
5256
5357 a.recycle()
5458 }
5559
56- private val textProcessor: FlowableProcessor < String > = PublishProcessor .create()
60+ private val textProcessor = PublishProcessor .create< String > ()
5761
58- private val compositeDisposable: CompositeDisposable = CompositeDisposable ()
62+ private val compositeDisposable = CompositeDisposable ()
5963
60- private val validators: ArrayList <VtlValidator > = ArrayList ()
64+ private val validators = ArrayList <VtlValidator >()
6165
62- private val mainHandler: Handler = HandlerProvider .createMainHandler()
66+ private val mainHandler = HandlerProvider .createMainHandler()
6367
6468 private val textWatcher = object : TextWatcher {
6569 override fun beforeTextChanged (s : CharSequence , start : Int , count : Int , after : Int ) {
@@ -71,30 +75,36 @@ class ValidatableTextInputLayout @JvmOverloads constructor(
7175 }
7276
7377 override fun afterTextChanged (s : Editable ) {
74- textProcessor.onNext(s.toString())
78+ if (! triggerAfterValidation) {
79+ textProcessor.onNext(s.toString())
80+ }
7581 }
7682 }
7783
7884 private val onCustomFocusChangeListener = OnFocusChangeListener { _, hasFocus ->
79- if (hasFocus) {
80- if (shouldValidateOnTextChanged || shouldValidateOnTextChangedOnce) {
81- shouldValidateOnTextChangedOnce = false
82- compositeDisposable.clear()
83- compositeDisposable.add(
84- Flowable .zip(validationFlowables) { Any () }
85- .doOnError({ this .showErrorMessage(it) })
86- .retry() // non-terminated stream
87- .subscribeOn(Schedulers .computation())
88- .subscribe({ clearErrorMessage() }, {})
89- )
90- }
91- } else {
92- if (shouldValidateOnFocusChanged) {
93- compositeDisposable.clear()
94- compositeDisposable.add(
95- validateAsCompletable().subscribe(Functions .EMPTY_ACTION , Consumer <Throwable > {})
96- )
85+ if (! triggerAfterValidation) {
86+
87+ if (hasFocus) {
88+ if (shouldValidateOnTextChanged || shouldValidateOnTextChangedOnce) {
89+ shouldValidateOnTextChangedOnce = false
90+ compositeDisposable.clear()
91+ compositeDisposable.add(
92+ Flowable .zip(validationFlowables) { Any () }
93+ .doOnError({ this .showErrorMessage(it) })
94+ .retry() // non-terminated stream
95+ .subscribeOn(Schedulers .computation())
96+ .subscribe({ clearErrorMessage() }, {})
97+ )
98+ }
99+ } else {
100+ if (shouldValidateOnFocusChanged) {
101+ compositeDisposable.clear()
102+ compositeDisposable.add(
103+ validateAsCompletable().subscribe(Functions .EMPTY_ACTION , Consumer <Throwable > {})
104+ )
105+ }
97106 }
107+
98108 }
99109 }
100110
@@ -221,6 +231,7 @@ class ValidatableTextInputLayout @JvmOverloads constructor(
221231 mainHandler.post {
222232 error = errorMessage
223233 isErrorEnabled = true
234+ triggerAfterValidation = false
224235 }
225236 }
226237 }
0 commit comments