github地址:https://github.com/itlwy/DBindingView
写在前面
一个对databinding的常用封装库,包含基础控件及recycleview等。不了解databinding的可以先阅读相关网上的资料,这里推荐
Android DataBinding介绍
缩略图
如何引入
step1
Add the JitPack repository to your build file
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
step2
Add the dependency
dependencies {
compile 'com.github.itlwy:DBindingView:v1.1.14'
}
如何使用
一般控件
如上面的动态图,目前展示了基本控件的进行一些初始化的封装,目的是将一些繁琐的初始化操作自动化掉。注意,这里用到的属性均是自定义属性,前缀请用app:
涉及到的类
类名 | 包名 | 说明 |
---|---|---|
KeyValue | com.lwy.dbindingview.data | 存储key(Integer)-value(String),主要用于spinner、checkbox、radiogroup等,实现数据源的key-label模式 |
BindingSpinner | com.lwy.dbindingview.bindingadapter.spinner | 封装的双向绑定自定义Spinner |
DataBindingRadioGroup | com.lwy.dbindingview.bindingadapter.radiogroup | 封装的双向绑定自定义RadioGroup |
DataBindingRadioButton | com.lwy.dbindingview.bindingadapter.radiogroup | 封装的双向绑定自定义RadioButton |
BindingCheckGroup | com.lwy.dbindingview.bindingadapter.checkbox | 封装的双向绑定自定义LinearLayout,用作BindingCheckBox容器 |
BindingCheckBox | com.lwy.dbindingview.bindingadapter.checkbox | 封装的双向绑定自定义CheckBox |
BindingEditText | com.lwy.dbindingview.bindingadapter.edittext.BindingEditText | 让EditText支持绑定数值类型,eg:Integer、Double… |
属性
控件 | 自定义属性 | 值类型 | 值 | 说明 |
---|---|---|---|---|
BindingSpinner | selectedValue | KeyValue | 绑定选中的值 | |
spinneritems | List<KeyValue> | spinner的适配器数据源 | ||
DataBindingRadioGroup | selectedValue | KeyValue | 绑定RadioGroup选中的值 | |
items | List<KeyValue> | 设置该属性可动态渲染子view | ||
childViewFactory | DBCustomViewFactory<DataBindingRadioButton> | 当设置了items属性时,可通过此属性传入继承自DataBindingRadioButton的自定义view,不设则用默认类 | ||
DataBindingRadioButton | value | KeyValue | 初始化RadioButton的值 | |
BindingCheckGroup | selectedValues | List<KeyValue> | 存储checkbox选中的值,默认用,分割 | |
items | List<KeyValue> | 设置该属性可动态渲染子view | ||
childViewFactory | DBCustomViewFactory<BindingCheckBox> | 当设置了items属性时,可通过此属性传入继承自BindingCheckBox的自定义view,不设则用默认类 | ||
BindingCheckBox | value | KeyValue | 设置值 | |
ImageView | uri | String or ObservableField | 图片的url,用的加载框架是glide | |
placeholderImageRes | int | eg:R.mipmap.ic_launcher | 占位图 | |
request_width、request_width | int | 设置图片的大小,不设置默认用view的大小,2个属性必修同时设置才有效 | ||
View | clickCommand | ReplyCommand | 点击事件触发的命令 | |
display | boolean | 控制view的Visibility | ||
BindingEdittext | textDouble、textInt、textFloat、textLong | Double、Float、Integer、Long | 绑定数值类型 | |
regularExpression | 正则表达式校验输入值 |
具体使用很简单,直接看demo–>com.lwy.dbindingview.base_widget.WidgeActivity
这里说明下DataBindingRadioGroup和BindingCheckGroup,
<com.lwy.dbindingview.bindingadapter.radiogroup.DataBindingRadioGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:layout_weight="10"
android:orientation="horizontal"
app:items="@{viewmodel.sexList}"
app:childViewFactory="@{ViewFactory.createDBRadioButton()}"
app:selectedValue="@={viewmodel.sex}"/>
这里的app:items属性,让其根据sexList动态渲染子view(DataBindingRadioButton),也可以选择在布局里直接写子View,如:
<com.lwy.dbindingview.bindingadapter.radiogroup.DataBindingRadioGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:layout_weight="10"
android:orientation="horizontal"
app:selectedValue="@={viewmodel.sex}">
<com.lwy.dbindingview.bindingadapter.radiogroup.DataBindingRadioButton
android:layout_width="wrap_content"
app:value="@{viewmodel.sex_male}"
android:layout_height="wrap_content"/>
<com.lwy.dbindingview.bindingadapter.radiogroup.DataBindingRadioButton
android:layout_width="wrap_content"
app:value="@{viewmodel.sex_female}"
android:layout_height="wrap_content"/>
</com.lwy.dbindingview.bindingadapter.radiogroup.DataBindingRadioGroup>
BindingCheckGroup同理
RecycleView
属性
属性 | 值类型 | 值 | 说明 |
---|---|---|---|
itemBinding | ItemBinding | 必填,item的布局和变量的绑定关系包装类 | |
items | List<T> | 必填,数据源 | |
adapter | BindingRecyclerViewAdapter<T> | 选填,可继承BindingRecyclerViewAdapter自定义适配器 | |
itemIds | BindingRecyclerViewAdapter.ItemIds<? super T> | 选填,不设置则默认使用position | |
viewHolder | BindingRecyclerViewAdapter.ViewHolderFactory | 选填,可继承以实现自定义ViewHolder | |
onItemClick | BindingRecyclerViewAdapter.OnItemClickListener | item点击事件 | |
layoutManager | LayoutManagers.LayoutManagerFactory | 必填,布局方式,如线性:LayoutManagers.linear() | |
代码说明
单个布局的简单列表代码片段
1、定义viewmodel
public class ItemVM extends BaseObservable { public final boolean checkable; // for now,it's useless @Bindable private int index; @Bindable private boolean checked; public ItemVM(int index, boolean checkable) { this.index = index; this.checkable = checkable; } public int getIndex() { return index; } public boolean isChecked() { return checked; } public boolean onToggleChecked(View v) { if (!checkable) { return false; } checked = !checked; // notifyPropertyChanged(com.lwy.dbindingview.BR.checked); return true; } }
2、定义Item布局文件R.layout.item
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="item" type="com.lwy.dbindingview.recycleview.vm.ItemVM" /> <import type="android.view.View" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?selectableItemBackground" android:onLongClickListener="@{item::onToggleChecked}" android:longClickable="@{item.checkable}" android:orientation="horizontal"> <TextView style="@style/TextAppearance.AppCompat.Body1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:padding="16dp" android:text='@{"Item " + (item.index + 1)}' tools:text="Item 1" /> <ImageView android:layout_width="48dp" android:layout_height="48dp" android:src="@mipmap/ic_action_check" android:visibility="@{item.checked ? View.VISIBLE : View.GONE}" /> </LinearLayout> </layout>
3、创建layout和viewmodel变量的绑定关系包装类
public final ItemBinding<ItemVM> singleItem = ItemBinding.of(com.lwy.dbindingview.BR.item, R.layout.item);
4、创建数据源
public final ObservableList<ItemVM> items = new ObservableArrayList<>();
5、设置RecycleView的属性
... <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" app:itemBinding="@{viewmodel.singleItem}" app:items="@{viewmodel.items}" app:layoutManager="@{LayoutManagers.linear()}"/> ...
复杂布局代码片段
1、定义viewmodel(同上)
2、定义Item布局文件R.layout.item(同上)
3、创建footer的viewmodel
public class FooterVM extends RcVFooterVM { public final ReplyCommand clickCommand = new ReplyCommand(new Action0() { @Override public void call() { if (!getIsFooterLoading().get()) { switchLoading(true); callback.execute(); } } }); private ReplyCommand callback;
public final ObservableField<String> noMoreTip = new ObservableField<>();
/*
state : 0 loading
state : 1 idle
*/
public final ObservableField<Integer> state = new ObservableField<>();
public FooterVM(ReplyCommand callback) {
super();
this.callback = callback;
switchLoading(false);
noMoreTip.set("暂无更多");
}
@Override
protected ReplyCommand<Integer> geneOnLoadMoreCommand() {
return new ReplyCommand<>(new Action1<Integer>() {
@Override
public void call(Integer integer) {
FooterVM.this.callback.execute();
// switchLoading(true);
}
});
}
@Override
public void switchLoading(boolean flag) {
if (flag) {
state.set(0);
} else {
state.set(1);
}
super.switchLoading(flag);
}
}
4、创建footer的布局文件R.layout.default_loading
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="footerVM"
type="com.lwy.dbindingview.recycleview.vm.FooterVM"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:clickCommand="@{footerVM.clickCommand}">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:orientation="horizontal"
android:padding="8dp"
app:display="@{footerVM.state==0?true:false}">
<ProgressBar
android:layout_width="32dp"
android:layout_height="32dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:text="正在加载..."
android:textSize="14sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:orientation="horizontal"
android:padding="8dp"
app:display="@{footerVM.state==1?true:false}">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="8dp"
android:text="@{footerVM.noMoreTip}"
android:textSize="14sp"/>
</LinearLayout>
</LinearLayout>
</layout>
5、创建layout和viewmodel变量的绑定关系包装类
// 这里根据class类型来控制不同的item
public final ItemBinding<Object> multipleItems = ItemBinding.of(new OnItemBindClass<>()
.map(FooterVM.class, BR.footerVM, R.layout.default_loading)
.map(String.class, com.lwy.dbindingview.BR.item, R.layout.item_header_footer)
.map(ItemVM.class, com.lwy.dbindingview.BR.item, R.layout.item));
6、创建数据源
public final FooterVM footerVM = new FooterVM(new ReplyCommand<Integer>(new Action1<Integer>() {
@Override
public void call(Integer integer) {
// 异步执行加载数据 完了需要调用 "footerVM.switchLoading(false)" 取消加载状态
}
}));
public final ObservableList<ItemVM> items = new ObservableArrayList<>();
public final MergeObservableList<Object> headerFooterItems = new MergeObservableList<>()
.insertItem("Header")
.insertList(items)
.insertItem(footerVM);
5、设置RecycleView的属性
...
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:itemBinding="@{viewmodel.multipleItems}"
app:items="@{viewmodel.headerFooterItems}"
app:layoutManager="@{LayoutManagers.linear()}"/>
...