举例:用户登录界面,通常的用户交互是:用户输入全部内容,点击“登录”,后台校验数据,返回结果。
进一步的体验:会对EditText的输入内容进行正则表达式,点击“登录”时,进行校验数据是否符合正则表达式,符合了再传数据到后台,不符合时弹出Toast进行提示。
更优的用户体验是什么呢?
我目前能想到的是:如下图所示,实时监听EditText,对输入的内容一直监听着,当两个EditText(也可同时监听当个、多个)都符合要求了,“登录”按钮才变色、可按(或者其它操作可自定义)
接下来,安装步骤实现:
一.引入相关依赖
api 'io.reactivex:rxandroid:1.2.0'
api 'io.reactivex.rxjava2:rxjava:2.0.1'
api 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
api 'com.jakewharton.rxbinding:rxbinding-design:0.4.0'
二.工具类 RxTextViewUtil
/**
* RxTextView对控件的监听如EditText、TextView、Button等,可以同时监听一个、两个、多个
* 需要传入被监听的、判断的条件、要做出的动作
* Created by Administrator on 2019/7/15
*
* @author mcl
*/
public class RxTextViewUtil {
/*Observable是从rx.Observable来的
* RxTextView有两个包来,rxbinding里面是Observable,rxbinding2是InitialValueObservable
* */
/**
* 监听单个
* observableView被监听的view
* RxTextViewListenter进行回调
* 不足之处:监听条件不能要固定好,不能传送过来
*/
public static void Fun1(final TextView observableView, final RxTextViewListenter callBack) {
Observable<CharSequence> observable = RxTextView.textChanges(observableView);
observable.map(new Func1<CharSequence, Boolean>() {
@Override
public Boolean call(CharSequence charSequence) {
return AppValidationUtils.isPassword(observableView.getText().toString().trim());
}
}).subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
//在这个地方可以实现是否满足过滤逻辑
if (aBoolean) {
//如果满足了过滤逻辑 设置可以点击并且设置背景
callBack.success();
} else {
//否则就设置背景不可点击
callBack.failure();
}
}
});
}
/**
* 监听两个
* observableView1、observableView2被监听
* RxTextViewListenter进行回调
* 不足之处:监听条件不能要固定好,不能传送过来
*/
public static void Fun2(final TextView observableView1, final TextView observableView2, final RxTextViewListenter callBack) {
Observable<CharSequence> observable1 = RxTextView.textChanges(observableView1);
Observable<CharSequence> observable2 = RxTextView.textChanges(observableView2);
Observable.combineLatest(observable1, observable2, new Func2<CharSequence, CharSequence, Boolean>() {
@Override
public Boolean call(CharSequence charSequence, CharSequence charSequence2) {
return CollectionUtils.isNotBlack(observableView1.getText().toString().trim()) && CollectionUtils.isNotBlack(observableView2.getText().toString().trim());
}
}).subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
//在这个地方可以实现是否满足过滤逻辑
if (aBoolean) {
//如果满足了过滤逻辑 设置可以点击并且设置背景
callBack.success();
} else {
//否则就设置背景不可点击
callBack.failure();
}
}
});
}
/**
* 监听多个
* */
public static void FunN(final TextView observableView1, final TextView observableView2, final TextView observableView3, final TextView observableView4, final RxTextViewListenter callBack) {
Observable<CharSequence> observable1 = RxTextView.textChanges(observableView1);
Observable<CharSequence> observable2 = RxTextView.textChanges(observableView2);
Observable<CharSequence> observable3 = RxTextView.textChanges(observableView3);
Observable<CharSequence> observable4 = RxTextView.textChanges(observableView4);
List<Observable<CharSequence>> observables = new ArrayList<>();
observables.add(observable1);
observables.add(observable2);
observables.add(observable3);
observables.add(observable4);
Observable.combineLatest(observables, new FuncN<Boolean>() {
@Override
public Boolean call(Object... args) {
return CollectionUtils.isNotBlack(observableView1.getText().toString().trim()) && CollectionUtils.isNotBlack(observableView2.getText().toString().trim()) &&
CollectionUtils.isNotBlack(observableView3.getText().toString().trim()) && CollectionUtils.isNotBlack(observableView4.getText().toString().trim());
}
}).subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
//在这个地方可以实现是否满足过滤逻辑
if (aBoolean) {
//如果满足了过滤逻辑 设置可以点击并且设置背景
callBack.success();
} else {
//否则就设置背景不可点击
callBack.failure();
}
}
});
}
}
三.调用(项目里面我用的是dataBinding数据绑定)
//监听单个控件,不足之处是,不能把判断条件传送过去,因为要实时监听,
//监听账号,进行后面提示
RxTextViewUtil.Fun1(mBinding.edLoginRxAccount, new RxTextViewListenter() {
@Override
public void success() {
mBinding.tvLoginRxAccount.setText("账号格式符合要求");
}
@Override
public void failure() {
mBinding.tvLoginRxAccount.setText("账号格式错误");
}
});
//监听两个,来控制登录button
RxTextViewUtil.Fun2(mBinding.etLoginAccount, mBinding.etLoginPassword, new RxTextViewListenter() {
@Override
public void success() {
mBinding.button.setBackgroundResource(R.mipmap.bt_determine_hover_bg);
mBinding.button.setText(ResourceUtil.getStringId(LoginActivity.this, "login_logining"));
mBinding.button.setEnabled(true);
}
@Override
public void failure() {
mBinding.button.setBackgroundResource(R.mipmap.bt_determine_normal_bg);
mBinding.button.setEnabled(false);
}
});
//监听四个(验证多个情况)
//监听上面两个,来控制登录button
RxTextViewUtil.FunN(mBinding.etLoginAccount, mBinding.etLoginPassword, mBinding.edLoginRxAccount, mBinding.edLoginRxPassword, new RxTextViewListenter() {
@Override
public void success() {
mBinding.btLoginRxlogin.setBackgroundResource(R.mipmap.bt_determine_hover_bg);
mBinding.btLoginRxlogin.setText(ResourceUtil.getStringId(LoginActivity.this, "login_logining_rx"));
mBinding.btLoginRxlogin.setEnabled(true);
}
@Override
public void failure() {
mBinding.btLoginRxlogin.setBackgroundResource(R.mipmap.bt_determine_normal_bg);
mBinding.btLoginRxlogin.setEnabled(false);
}
});
四.完工