I think in order to handle it in a clean way, each view should keep their validation logic and their valid status. We shouldn't use same code lines in each screen.
For ex: if you have a phone number field, you shouldn't write its validation logic in every screen. You can create a custom view for phone field and keep its validation logic inside that custom view. By this you will get rid of field validation in each screen
But it is not finished yet, you can also handle on valid state inside your custom button view. By this you will eliminate duplicate lines of valid state handling from your screens.
And at last you need to just a logic to introduce input fields to your button
I have extracted all these logic as a lib and added simple demo for its usage.
To use it you need to just implement an interface in your custom input views and another interface in your custom button.
Then you can bind all inputs to your button with one line of code in each screen
Demo.gif
Usage
For Input Field: You need to implement Validatable
interface in your input field. 2 methods will be implemented in here.
In this example our custom input view extends AppCompatEditText
/**
* Validity State of View
* In here input field is valid if any text is entered
* */
override val isValid: Boolean
get() = length() > 0
/**
* Informing Validator about change in input field
* In here we are rechecking validity every time on after text change
* */
override fun setupValidationListener(validator: Validator?) {
addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
/**
* To inform Validator view is changed
* */
override fun afterTextChanged(p0: Editable?) {
validator?.checkAll()
}
})
}
For Output view(Button in most cases): You need to implement Verifier interface which handles onValid state of button. This method will be invoked if every input in page is valid.
/**
* Enabling button if validator informs that all inputs are valid
*/
override fun onValid(isValid: Boolean) {
isEnabled = isValid
}
Binding input and output views: You have add this line to your activity/fragment for validation binding. First variable is your Verifier view then you can add all of your Validatable views, there is no Validatable view limit
ValidationBinder.bind(bindind.btnContinue, bindind.inputFirst, bindind.inputSecond)