1. 背景
我们经常在开发中会遇到一些类似采集信息的界面,有若干必填项,当必填项填写完成之后,才可以进行下一步,换句话来说就是当所有必填项的 EditText 都填写完内容之后,下一步的按钮才可以点击。
类似下图的效果:
一般的我们代码的实现是这样的:需要监听 EditText 的 TextChangedListener,然后对 Button 的状态进行改变。部分关键代码如下:
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(TextUtils.isEmpty(s)){
btn.setEnabled(false);
}else{
btn.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
对 Button 的 background 和 textcolor 设置为相应的 selector 即可。
shape_btn_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_btn_enabled" android:state_enabled="true"/>
<item android:drawable="@drawable/shape_btn_no_enabled" />
</selector>
假设我们现在有 3 个 EditText 都是必填项,那我们可能会这么写:
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(TextUtils.isEmpty(s) && TextUtils.isEmpty(et2.getText().toString()) && TextUtils.isEmpty(et3.getText().toString())){
btn.setEnabled(false);
}else{
btn.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
et2.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(TextUtils.isEmpty(s) && TextUtils.isEmpty(et.getText().toString()) && TextUtils.isEmpty(et3.getText().toString())){
btn.setEnabled(false);
}else{
btn.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
et3.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(TextUtils.isEmpty(s) && TextUtils.isEmpty(et2.getText().toString()) && TextUtils.isEmpty(et.getText().toString())){
btn.setEnabled(false);
}else{
btn.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
代码量长且不易观看,容易出问题。
2. 改进
虽然上述方式可以实现我们想要的效果,但是如果我们有多个 EditText,就需要我们对每个 EditText 都做类似的监听,并且我们需要每次判断其它是否也输入了,代码中就会充斥着很多相似的一些代码,而且极容易出现问题,所以需要设计一个工具类对我们所有需要监听的 EditText 做一个统一的处理,只留一个回调返回给前台,确定Button是否可用。
设计一个 InputWatcherUtils 工具类,里面有一个 watch 方法,传入我们需要监听的 EditText,我们在工具类中做统一的处理,代码如下:
/**
* edit by qq 2021
*/
public class InputWatcherUtils {
private InputWatcherUtils(){}
private static InputWatcherUtils instance;
private OnStatusChangedListener listener;
public static InputWatcherUtils getInstance(){
if(null == instance){
instance = new InputWatcherUtils();
}
return instance;
}
private EditText[] editTexts;
public InputWatcherUtils watch(EditText... et){
this.editTexts = et;
init();
return this;
}
private void init() {
for(EditText et : editTexts){
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
boolean isEnable = checkAllEditText();
if(null != listener){
listener.onChanged(isEnable);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
}
private boolean checkAllEditText() {
//遍历所有的 EditText 判断填写内容
for(EditText et : editTexts){
if(TextUtils.isEmpty(et.getText().toString())){
return false;
}else{
continue;
}
}
return true;
}
public interface OnStatusChangedListener{
void onChanged(boolean isEnable);
}
public void setOnStatusChangedListener(OnStatusChangedListener listener){
this.listener = listener;
}
}
然后对于前端 Activity 我们就可以这个调用,假如我们有一个 EditText:
InputWatcherUtils.getInstance().watch(et).setOnStatusChangedListener(new InputWatcherUtils.OnStatusChangedListener() {
@Override
public void onChanged(boolean isEnable) {
if(isEnable){
//如果已经是可用的状态就不需要再设置一次了
if(!btn.isEnabled()){
btn.setEnabled(true);
}
}else{
btn.setEnabled(false);
}
}
});
而如果我们有多个 EditText ,只需要多传递几个参数即可,像这样:
InputWatcherUtils.getInstance().watch(et,et2,et3).setOnStatusChangedListener(new InputWatcherUtils.OnStatusChangedListener() {
@Override
public void onChanged(boolean isEnable) {
if(isEnable){
//如果已经是可用的状态就不需要再设置一次了
if(!btn.isEnabled()){
btn.setEnabled(true);
}
}else{
btn.setEnabled(false);
}
}
});
最后,运行看下是否能达到我们想要的效果:
看效果完全没任何问题,有问题评论区见哦~