RxJava<第二十四篇>:RxBinding3.0
(1)github
以下是RxBing的github地址:
目前RxBinding已经更新到3.0.0-alpha2
了。
(2)依赖
RxBinding2.0.0使用量比较多:
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
RxBinding2.2.0之后废弃了一些组件和接口
implementation 'com.jakewharton.rxbinding2:rxbinding:2.2.0'
图片.png
图片.png
另外RxBinding2.2.0提供了对recyclerview组件的扩展
implementation 'com.jakewharton.rxbinding2:rxbinding-recyclerview-v7:2.2.0'
图片.png
图片.png
如果用到recyclerview的话可以选择使用 recyclerview-v7:2.2.0
这个依赖。
RxBinding现在已经更新到3.0.0了:
我们可以使用以下依赖
implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'
同时,在2.0.0的基础上废弃了不少接口。
RxBinding3.0.0加入了对AndroidX的支持
implementation 'com.jakewharton.rxbinding3:rxbinding-core:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-appcompat:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-drawerlayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-leanback:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-recyclerview:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-slidingpanelayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-swiperefreshlayout:3.0.0-alpha2'
implementation 'com.jakewharton.rxbinding3:rxbinding-viewpager:3.0.0-alpha2'
包括Google 'material' library bindings:
implementation 'com.jakewharton.rxbinding3:rxbinding-material:3.0.0-alpha2'
也需要AndroidX的支持。
随着Android SDK版本的迭代,api28之后将不再更新,将传统项目转成AndoridX刻不容缓,RxBinding对AndroidX的支持以后应该还会继续迭代。
本章将针对
implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'
这个依赖包进行分析。
还有一点需要说明,如果项目中已经导入了以下依赖包,可以直接删除了,因为RxBinding的依赖包自带rxjava和rxandroid。
implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
(3)相关组件
RxAbsListView
、RxAdapter
、RxAdapterView
、RxAutoCompleteTextView
、RxCompoundButton
、RxPopupMenu
、RxRadioGroup
、RxRatingBar
、RxSearchView
、RxSeekBar
、RxTextView
、RxToolbar
、RxMenuItem
、RxView
、RxViewGroup
(4)RxView
-
clicks 点击事件
RxView.clicks(bt_1).subscribe(new Consumer<Object>() { @Override public void accept(Object o) throws Exception { Log.d("aaa", "点击事件"); } });
相当于
bt_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("aaa", "点击事件");
}
});
- visibility 隐藏或者显示
方法一:
boolean value = false;
try {
RxView.visibility(bt_1).accept(value);
} catch (Exception e) {
e.printStackTrace();
}
相当于
boolean value = false;
bt_1.setVisibility(value ? View.VISIBLE : View.GONE);
方法二:
boolean value = false;
int visibilityWhenFalse = View.VISIBLE;
try {
RxView.visibility(bt_1, visibilityWhenFalse).accept(value);
} catch (Exception e) {
e.printStackTrace();
}
相当于
boolean value = false;
int visibilityWhenFalse = View.VISIBLE;
bt_1.setVisibility(value ? View.VISIBLE : visibilityWhenFalse);
-
longClicks 长按事件
RxView.longClicks(bt_1) .subscribe(new Consumer<Unit>() { @Override public void accept(Unit unit) throws Exception { Log.d("aaa", "1111111111111111"); } });
相当于
bt_1.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Log.d("aaa", "1111111111111111");
return false;
}
});
- attaches View被添加
RxView.attaches(bt_1);
- attachEvents View被添加时触发
RxView.attachEvents(bt_1)
- detaches View被移除
RxView.detaches(bt_1);
-
drags 拖拽的监听
RxView.drags(ll_demo) .subscribe(new Consumer<DragEvent>() { @Override public void accept(DragEvent event) throws Exception { //获取事件 int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: Log.d("aaa", "开始拖拽"); break; case DragEvent.ACTION_DRAG_ENDED: Log.d("aaa", "结束拖拽"); break; case DragEvent.ACTION_DRAG_ENTERED: Log.d("aaa", "拖拽的view进入监听的view时"); break; case DragEvent.ACTION_DRAG_EXITED: Log.d("aaa", "拖拽的view离开监听的view时"); ll_demo.setBackgroundColor(Color.parseColor("#303F9F")); break; case DragEvent.ACTION_DRAG_LOCATION: float x = event.getX(); float y = event.getY(); ll_demo.setBackgroundColor(Color.GRAY); Log.i("aaa", "拖拽的view在监听view中的位置:x =" + x + ",y=" + y); break; case DragEvent.ACTION_DROP: Log.i("aaa", "释放拖拽的view"); if(event != null && event.getLocalState() != null){ View localState = (View) event.getLocalState(); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ((ViewGroup) localState.getParent()).removeView(localState); ll_demo.addView(localState, layoutParams); } break; } } });
RxView.longClicks(bt_1)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
//设置震动反馈
bt_1.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
// 创建DragShadowBuilder,我把控件本身传进去
View.DragShadowBuilder builder = new View.DragShadowBuilder(bt_1);
// 剪切板数据,可以在DragEvent.ACTION_DROP方法的时候获取。
ClipData data = ClipData.newPlainText("Label", "我是文本内容!");
// 开始拖拽
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
bt_1.startDragAndDrop(data, builder,bt_1, 0);
}else{
bt_1.startDrag(data, builder, bt_1, 0);
}
}
});
效果如下:
40.gif- draws 重绘监听
监听某View重绘
随便自定义一个view吧
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr, 0);
}
int[] colors = {Color.RED, Color.BLACK, Color.CYAN, Color.BLUE};
int index = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(colors[index]);
Log.d("aaa", String.valueOf(index));
index = (++index >= colors.length) ? 0 : index;
postInvalidateDelayed(1000);
}
}
效果如下
41.gif现在开始监听
RxView.draws(view_demo)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
Log.d("aaa", "22222");
}
});
相当于
view_demo.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
@Override
public void onDraw() {
Log.d("aaa", "22222");
}
});
- globalLayouts 监听布局改变
在弹出软键盘,使布局变化的场景常用
RxView.globalLayouts(rootview)
.subscribe(new Consumer<Unit>() {
@Override
public void accept(Unit unit) throws Exception {
Log.d("aaa", "1111111111111111111");
}
});
相当于
rootview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.d("aaa", "1111111111111111111");
}
});
-
focusChanges 监听焦点变化
RxView.focusChanges(et_demo) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { Log.d("aaa", "11111111111111"); } });
相当于
et_demo.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
Log.d("aaa", "11111111111111");
}
});
- hovers 悬停事件
一些平板支持鼠标,当鼠标悬停在某view上时,会有其他效果
图片.png比如给按钮添加背景,设置state_hovered属性, 当鼠标悬停在view上时会改变颜色。
我们也可以对悬停事件进行监听
RxView.hovers(bt_1)
.subscribe(new Consumer<MotionEvent>() {
@Override
public void accept(MotionEvent motionEvent) throws Exception {
Log.d("aaa", "11111111111111");
int what = motionEvent.getAction();
switch(what){
case MotionEvent.ACTION_HOVER_ENTER: //鼠标进入view
break;
case MotionEvent.ACTION_HOVER_MOVE: //鼠标在view上
break;
case MotionEvent.ACTION_HOVER_EXIT: //鼠标离开view
break;
}
}
});
相当于
bt_1.setOnHoverListener(new View.OnHoverListener() {
@Override
public boolean onHover(View v, MotionEvent event) {
Log.d("aaa", "11111111111111");
int what = event.getAction();
switch(what){
case MotionEvent.ACTION_HOVER_ENTER: //鼠标进入view
break;
case MotionEvent.ACTION_HOVER_MOVE: //鼠标在view上
break;
case MotionEvent.ACTION_HOVER_EXIT: //鼠标离开view
break;
}
return false;
}
});
- keys 按键被按下
主要用作于监听物理按键的返回键,当然,软键盘的删除和回车(搜索)也是可以监听到的。
RxView.keys(et_demo)
.subscribe(new Consumer<KeyEvent>() {
@Override
public void accept(KeyEvent keyEvent) throws Exception {
Log.d("aaa", "11111111111111");
}
});
相当于
et_demo.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d("aaa", "11111111111111:"+event.getAction());
return false;
}
});
-
layoutChanges和layoutChangeEvents 组件布局参数发生改变
RxView.layoutChanges(rootview) .subscribe(new Consumer<Unit>() { @Override public void accept(Unit unit) throws Exception { Log.d("aaa", "1111111111111111111"); } });
RxView.layoutChangeEvents(rootview)
.subscribe(new Consumer<ViewLayoutChangeEvent>() {
@Override
public void accept(ViewLayoutChangeEvent viewLayoutChangeEvent) throws Exception {
Log.d("aaa", "1111111111111111111");
}
});
相当于
rootview.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
Log.d("aaa", "1111111111111111111");
}
});
- preDraws 将要绘制时
熟悉自定义view或者viewgroup的猿一定知道三个方法:onMeasure
、onLayout
、onDraw
,它们的执行顺序是onMeasure
-->onLayout
-->onDraw
, preDraws
监听的时机就在onLayout
和onDraw
之间。
RxView.preDraws(view_demo, new Function0<Boolean>() {
@Override
public Boolean invoke() {
return false;
}
})
.subscribe(new Observer<Unit>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(Unit unit) {
Log.d("aaa", "onPreDraw");
//接收一次之后立即移除监听,否则会阻塞UI线程
disposable.dispose();
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
相当于
view_demo.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
Log.d("aaa", "onPreDraw");
//监听一次之后立即移除监听,否则会阻塞UI线程
view_demo.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
- scrollChangeEvents 滚动事件API23
这个监听在API 23之后生效
RxView.scrollChangeEvents(view_demo)
.subscribe(new Consumer<ViewScrollChangeEvent>() {
@Override
public void accept(ViewScrollChangeEvent viewScrollChangeEvent) throws Exception {
}
});
相当于
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view_demo.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
}
});
}
-
systemUiVisibilityChanges 状态栏和导航栏可见和隐藏
RxView.systemUiVisibilityChanges(rootview) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { } });
相当于
rootview.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
}
});
-
touches 触摸事件
RxView.touches(et_demo) .subscribe(new Consumer<MotionEvent>() { @Override public void accept(MotionEvent motionEvent) throws Exception { } });
相当于
et_demo.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
(5)RxTextView
- beforeTextChangeEvents、textChanges、textChangeEvents、afterTextChangeEvents
对文本变化监听。
RxTextView.beforeTextChangeEvents(et_demo)
.subscribe(new Consumer<TextViewBeforeTextChangeEvent>() {
@Override
public void accept(TextViewBeforeTextChangeEvent textViewBeforeTextChangeEvent) throws Exception {
Log.d("aaa", "111111111111111");
}
});
RxTextView.textChangeEvents(et_demo)
.subscribe(new Consumer<TextViewTextChangeEvent>() {
@Override
public void accept(TextViewTextChangeEvent textViewTextChangeEvent) throws Exception {
Log.d("aaa", "2222222222222222222");
}
});
RxTextView.afterTextChangeEvents(et_demo)
.subscribe(new Consumer<TextViewAfterTextChangeEvent>() {
@Override
public void accept(TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception {
Log.d("aaa", "3333333333333333333333");
}
});
相当于
et_demo.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) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
-
editorActions和editorActionEvents
RxTextView.editorActions(et_demo) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.d("aaa", String.valueOf(integer)); } });
RxTextView.editorActionEvents(et_demo)
.subscribe(new Consumer<TextViewEditorActionEvent>() {
@Override
public void accept(TextViewEditorActionEvent textViewEditorActionEvent) throws Exception {
Log.d("aaa", "1111111111111111111111");
}
});
相当于
et_demo.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});
需要注意的是:在布局文件中需要添加inputType和imeOptions属性。
(6)RxViewGroup
- changeEvents
当viewgroup添加或者删除子view时触发
rootview.addView(view);
rootview.removeView(view);
代码如下:
RxViewGroup.changeEvents(rootview)
.subscribe(new Consumer<ViewGroupHierarchyChangeEvent>() {
@Override
public void accept(ViewGroupHierarchyChangeEvent viewGroupHierarchyChangeEvent) throws Exception {
Log.d("aaa", "11111111111111111111");
}
});
相当于
rootview.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
Log.d("aaa", "11111111111111111111");
}
@Override
public void onChildViewRemoved(View parent, View child) {
Log.d("aaa", "22222222222222222222");
}
});
(7)RxToolbar
-
navigationClicks
RxToolbar.navigationClicks(toolbar_normal).subscribe(new Consumer<Unit>() { @Override public void accept(Unit unit) throws Exception { } });
相当于
toolbar_normal.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
-
itemClicks
RxToolbar.itemClicks(toolbar_normal).subscribe(new Consumer<MenuItem>() { @Override public void accept(MenuItem menuItem) throws Exception { } });
相当于
toolbar_normal.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.action_item_one:
break;
case R.id.action_item_two:
break;
case R.id.action_notification:
break;
case R.id.action_search:
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setQueryHint("搜索");
break;
}
return true;
}
});
(8)RxMenuItem
-
clicks
RxMenuItem.clicks(menuItem) .subscribe(new Consumer<Unit>() { @Override public void accept(Unit unit) throws Exception { } });
对应着Toolbar某Item的点击事件
-
actionViewEvents
RxMenuItem.actionViewEvents(menuItem) .subscribe(new Consumer<MenuItemActionViewEvent>() { @Override public void accept(MenuItemActionViewEvent menuItemActionViewEvent) throws Exception { } });
对应着Toolbar某Item的点击事件
(9)RxRadioGroup
- checkedChanges
监听选中变化
RxRadioGroup.checkedChanges(radio_g).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
相当于
radio_g.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
}
});
- checked
选择单选按钮
try {
RxRadioGroup.checked(radio_g).accept(radioButton2.getId());
} catch (Exception e) {
e.printStackTrace();
}
相当于
radio_g.check(radioButton2.getId());
(10)RxCompoundButton
单选按钮
RxCompoundButton.checkedChanges(radioButton1)
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean isChecked) throws Exception {
}
});
相当于
radioButton1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
}
});
(11)RxAutoCompleteTextView
Item点击事件监听
RxAutoCompleteTextView.itemClickEvents(auto_tv)
.subscribe(new Consumer<AdapterViewItemClickEvent>() {
@Override
public void accept(AdapterViewItemClickEvent adapterViewItemClickEvent) throws Exception {
}
});
(12)RxPopupMenu
-
itemClicks
RxPopupMenu.itemClicks(popupMenu) .subscribe(new Consumer<MenuItem>() { @Override public void accept(MenuItem menuItem) throws Exception { }
相当于
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override public boolean onMenuItemClick(MenuItem item) {
// 控件每一个item的点击事件
return true;
}
});
-
dismisses
RxPopupMenu.dismisses(popupMenu).subscribe(new Consumer<Unit>() { @Override public void accept(Unit unit) throws Exception { } }); });
相当于
popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override public void onDismiss(PopupMenu menu) {
// 控件消失时的事件
}
});
(13)RxAdapter、RxAbsListView、RxAdapterView
适配器和listview相关,这个相信大家已经很熟悉了,这里不做过多介绍。
//适配器Adapter数据改变
RxAdapter.dataChanges();
//绝对视图滚动事件
RxAbsListView.scrollEvents();
RxAdapterView.selectionEvents();
RxAdapterView.itemSelections();
RxAdapterView.itemClicks();
RxAdapterView.itemLongClicks();
RxAdapterView.itemLongClickEvents();
(14)RxSeekBar
进度条相关监听
RxSeekBar.userChanges(seekBar).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
RxSeekBar.systemChanges(seekBar).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
RxSeekBar.changeEvents(seekBar).subscribe(new Consumer<SeekBarChangeEvent>() {
@Override
public void accept(SeekBarChangeEvent seekBarChangeEvent) throws Exception {
}
});
RxSeekBar.changes(seekBar).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
(15)RxRatingBar
RatingBar用作评分的进度条
图片.png比如上图, 用手指拖动可以进行评分。
//星级滚动条进度改变事件
RxRatingBar.ratingChanges();
//星级滚动条进度改变事件
RxRatingBar.ratingChangeEvents();
它的用法比较简单,这里就不写完整代码了。
(16)RxSearchView
SearchView的一般监听写法是
search_view.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
//提交后的处理
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
//输入文本监听,newText是文本变化后的文本
return true;
}
});
- queryTextChanges
输入文本监听,文本变化后的文本
RxSearchView.queryTextChanges(search_view)
.subscribe(new Consumer<CharSequence>() {
@Override
public void accept(CharSequence charSequence) throws Exception {
//输入文本监听,文本变化后的文本
Log.d("aaa", charSequence.toString());
}
});
-
queryTextChangeEvents
RxSearchView.queryTextChangeEvents(search_view).subscribe(new Consumer<SearchViewQueryTextEvent>() { @Override public void accept(SearchViewQueryTextEvent searchViewQueryTextEvent) throws Exception { if(searchViewQueryTextEvent.isSubmitted()){ //提交后的处理 }else{ //输入文本监听 } } });
-
query
try { //设置SearchView的初始值 RxSearchView.query(search_view, true).accept("asd"); } catch (Exception e) { e.printStackTrace(); }