有时我们需要知道根据edittext是否有输入内容来改变button的状态,常见的页面就是登录,只要用户没有输入手机号和密码时,button的状态为不可点击,且在UI在表现出来,如何优雅的判断多个edittext的内容呢?
效果
下图的需求是,当用户输入手机号及勾选协议后才能让button处于可点击状态,最简单的做法是分别为edittext和checkbox设置监听,然后设置一个成员变量来进行判断
ezgif.com-video-to-gif.gif
示例代码
这里你只需要将要观察的textview传递给Rule子类即可,Rule是一个抽象类,你可以实现你要判断的规则,我提供了手机号规则(中国),不为空规则和选中规则,使用方式如下。当所有的rule为true或false时会将结果回调给接口,(只有上次的结果与当前结果不同时才会执行回调,即上次为false当前结果也为false时,不执行callback方法)
Watcher.subscribe(new Watcher.Mobile(etMobileNumber), new Watcher.Checked(cbProtocol))
.setWatcherCallback(enabled -> {
butNext.setEnabled(enabled);
tvPasswordLogin.setEnabled(enabled);
});
源码
public class Watcher {
public static Watcher subscribe(Rule... rules) {
return new Watcher(rules);
}
private OnWatcherCallback mCallback;
private boolean mPreWatchResult = false;
private Map<TextView, Boolean> mObservedMap;
private Watcher(Rule... rules) {
mObservedMap = new ArrayMap<>();
for (Rule rule : rules) {
mObservedMap.put(rule.mObserved, rule.validation(rule.mObserved.getText()));
if (rule.mObserved instanceof EditText) {
rule.mObserved.addTextChangedListener(new EditTextTextWatcher(rule));
} else if (rule.mObserved instanceof CheckBox) {
CheckBox checkBox = (CheckBox) rule.mObserved;
checkBox.setOnCheckedChangeListener(new CheckedChangeListener(rule));
}
}
}
private void watchResult(Rule rule, boolean result) {
mObservedMap.put(rule.mObserved, result);
Collection<Boolean> values = mObservedMap.values();
if (mCallback != null) {
boolean watchResult = !values.contains(Boolean.FALSE);
if (watchResult != mPreWatchResult) {
mPreWatchResult = watchResult;
mCallback.callback(watchResult);
}
}
}
public void setWatcherCallback(OnWatcherCallback callback) {
this.mCallback = callback;
}
private class CheckedChangeListener implements CheckBox.OnCheckedChangeListener {
private final Rule mRule;
CheckedChangeListener(Rule rule) {
this.mRule = rule;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
watchResult(this.mRule, isChecked);
}
}
private class EditTextTextWatcher extends SimpleTextWatcher {
private final Rule mRule;
EditTextTextWatcher(Rule rule) {
this.mRule = rule;
}
@Override
public void afterTextChanged(Editable s) {
watchResult(this.mRule, this.mRule.validation(s));
}
}
/**
* 观察结果回调
*/
public interface OnWatcherCallback {
void callback(boolean watch);
}
public interface Rule {
boolean validation(CharSequence charSequence);
}
/**
* 单一规则
*/
public abstract static class SingleRule implement Rule {
TextView mObserved;
public Rule(TextView observed) {
this.mObserved = observed;
}
}
/**
* 选中
*/
public static class Checked extends SingleRule {
public CheckBox mObserved;
public Checked(CheckBox observed) {
super(observed);
this.mObserved = observed;
}
@Override
public boolean validation(CharSequence charSequence) {
return this.mObserved.isChecked();
}
}
/**
* 不为空
*/
public static class NotEmpty extends SingleRule {
public NotEmpty(EditText editText) {
super(editText);
}
@Override
public boolean validation(CharSequence charSequence) {
return !TextUtils.isEmpty(charSequence);
}
}
/**
* 手机号
*/
public static class Mobile extends SingleRule {
private final String REGEX_MOBILE =
"^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
public Mobile(EditText editText) {
super(editText);
}
@Override
public boolean validation(CharSequence charSequence) {
return Pattern.matches(REGEX_MOBILE, this.mObserved.getText());
}
}
}
网友评论