效果图
这是前段时间做得一个项目需求,要求能够选择选择第二级和第三级的一个三级列表,话不多说了,看代码吧
一、项目配置
//这个是databing的
android {
dataBinding {
enabled = true
}
}
//这是用到的依赖包,个人习惯,可以根据自己的方式调整
compile 'io.reactivex:rxjava:1.2.4'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.kelin.mvvmlight:library:1.0.0'
//一个Android MVVM 轻量级工具库,里面添加了一些Data Binding 不支持的属性,还有添加对控件事件的封装,同时提个一个全局消息通道方便ViewModel 之间的通信,Toolkit主要包括两部分Binding和Messenger
compile 'com.google.code.gson:gson:2.2.4'//用来解析json的
二、代码和布局
activity_choice_job_category.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="me.tatarka.bindingcollectionadapter.LayoutManagers" />
<variable
name="viewModel"
type="com.daxue.databingtestdemo.viewmodel.JobCategoryViewModel" />
data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.daxue.databingtestdemo.activity.ChoiceJobCategoryActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/colorPrimary"
android:text="选择"
android:textColor="@color/white"
android:gravity="center"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/bg_gray"
android:orientation="horizontal"
android:visibility="@{viewModel.showLabel ? View.VISIBLE : View.GONE}">
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{viewModel.leftText}"
bind:clickCommand="@{viewModel.leftTextClickCommand}"
android:visibility="@{viewModel.leftVisible ? View.VISIBLE : View.GONE}" />
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{viewModel.middleText}"
bind:clickCommand="@{viewModel.middleTextClickCommand}"
android:visibility="@{viewModel.middleVisible ? View.VISIBLE : View.GONE}" />
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{viewModel.rightText}"
bind:clickCommand="@{viewModel.rightTextClickCommand}"
android:visibility="@{viewModel.rightVisible ? View.VISIBLE : View.GONE}" />
LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:itemView="@{viewModel.itemView}"
bind:items="@{viewModel.itemViewModels}"
bind:layoutManager="@{LayoutManagers.linear()}" />
LinearLayout>
layout>
Data Binding的好处,直接用精简的代码实现数据与UI和逻辑的绑定,不需要编写大量的毫无营养繁琐的的代码,如 findViewById()、setText(),setVisibility(),setEnabled() 或 setOnClickListener() 等通通不需要
ChoiceJobCategoryActivity.java
public class ChoiceJobCategoryActivity extends AppCompatActivity {
private ActivityChoiceJobCategoryBinding binding;//这个是自动生成滴
private JobCategoryViewModel viewModel;
private ArrayList list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new JobCategoryViewModel(this);
//前面带过来已选中的数据
list = getIntent().getParcelableArrayListExtra("selected");
if (list != null) {
viewModel.setChoicePositions(list);
}
binding = DataBindingUtil.setContentView(this, R.layout.activity_choice_job_category);
binding.setViewModel(viewModel);
viewModel.start();
}
public void initLayout() {
binding.recyclerView.getAdapter().notifyDataSetChanged();
}
@Override
protected void onDestroy() {
super.onDestroy();
Messenger.getDefault().unregister(this);
}
}
这个页面实际上是一个过渡页面,起到一个桥梁的作用,实现activity与布局的绑定,主要的逻辑在viewmodel里面去实现
恩,下面才是重头戏
JobCategoryViewModel
public class JobCategoryViewModel extends BaseViewModel {
public static final String TAG = JobCategoryViewModel.class.getSimpleName();
public static final String EXTRA_SINGLE = "single";
private ChoiceJobCategoryActivity activity;
private boolean isSingle;
private ArrayList choicePositions = new ArrayList<>();
private List data = new ArrayList<>();
private ArrayList choicePositionsValues = new ArrayList<>();
public final ObservableList itemViewModels = new ObservableArrayList<>();
public final ObservableList childItemViewModels = new ObservableArrayList<>();
public final ObservableField arrow = new ObservableField<>();
public final ObservableBoolean showLabel = new ObservableBoolean(false);
public final ObservableBoolean leftVisible = new ObservableBoolean(false);
public final ObservableBoolean middleVisible = new ObservableBoolean(false);
public final ObservableBoolean rightVisible = new ObservableBoolean(false);
public final ObservableField leftText = new ObservableField<>();
public final ObservableField middleText = new ObservableField<>();
public final ObservableField rightText = new ObservableField<>();
public final ObservableField tot alCount = new ObservableField<>();
public final ObservableField percent = new ObservableField<>("0");
//三级列表分不同的布局,分别是case1,2,3
public final ItemViewSelector itemView = new ItemViewSelector() {
@Override
public void select(ItemView itemView, int position, TreeItemViewModel item) {
int itemType = item.getTreeModel().isRootNode();
switch (itemType) {
case 1:
itemView.set(BR.viewModel, R.layout.item_tree_group);
break;
case 2:
itemView.set(BR.viewModel, R.layout.item_tree_root);
break;
case 3:
itemView.set(BR.viewModel, R.layout.item_tree_leaf);
break;
}
}
@Override
public int viewTypeCount() {
return 3;
}
};
//初始化上次选中的页面
public void setChoicePositions(ArrayList choicePositions) {
this.choicePositions.clear();
ArrayList choiceItemViewModels = new ArrayList<>();
for (TreeModel treeModel : choicePositions) {
choiceItemViewModels.add(new TreeItemViewModel(activity, treeModel));
}
this.choicePositions.addAll(choiceItemViewModels);
percent.set(choicePositions.size() + "");
setLabel();
}
//初始化数据
public JobCategoryViewModel(final ChoiceJobCategoryActivity activity) {
this.activity = activity;
isSingle = activity.getIntent().getBooleanExtra(EXTRA_SINGLE, false);
arrow.set(activity.getResources().getDrawable(R.mipmap.icon_down));
//监听treeitemviewmodel一级列表的展开
Messenger.getDefault().register(activity, String.class, new Action1() {
@Override
public void call(String id) {
ArrayList removeItems = new ArrayList<>();
ArrayList removechildItems = new ArrayList<>();
for (TreeItemViewModel itemViewModel : itemViewModels) {
if (itemViewModel.getTreeModel().getPid().equals(id)) {
removeItems.add(itemViewModel);
}
for (TreeItemViewModel childitemViewModel : itemViewModels) {
if (childitemViewModel.getTreeModel().getPid().equals(itemViewModel.getTreeModel().getId())) {
removechildItems.add(childitemViewModel);
}
}
}
if (removeItems.size() > 0) {
itemViewModels.removeAll(removeItems);
itemViewModels.removeAll(removechildItems);
activity.initLayout();
} else {
getGroupNodes(id, "");
}
removeItems.clear();
removechildItems.clear();
}
}
);
//监听treeitemviewmodel 二级列表的展开
Messenger.getDefault().register(activity, Integer.class, new Action1() {
@Override
public void call(Integer integer) {
// ToastUtil.getInstance().show("yijind");
ArrayList removeItems = new ArrayList<>();
for (TreeItemViewModel itemViewModel : itemViewModels) {
if (itemViewModel.getTreeModel().getPid().equals(integer + "")) {
removeItems.add(itemViewModel);
}
}
if (removeItems.size() > 0) {
itemViewModels.removeAll(removeItems);
activity.initLayout();
} else {
getChildNodes(integer + "", "");
}
removeItems.clear();
}
});
//监听treeitemviewmodel二级和一级 checkbox的选中和移除
Messenger.getDefault().register(activity, TreeItemViewModel.class, new Action1() {
@Override
public void call(TreeItemViewModel viewModel) {
int removeCount = 0;
if (isSingle) {//单选---->回绑已ok
choicePositions.clear();
if (itemViewModels != null && itemViewModels.size() > 0) {
for (int i = 0; i < itemViewModels.size(); i++) {
itemViewModels.get(i).isChoice.set(false);
}
}
viewModel.isChoice.set(true);
choicePositions.add(viewModel);
} else {
if (choicePositions != null && choicePositions.size() > 0) {
for (int i = 0; i < choicePositions.size(); i++) {
TreeItemViewModel item = choicePositions.get(i);
if (item.getTreeModel().getId().equals(viewModel.getTreeModel().getId())) {
choicePositions.remove(i);//已经选过了,再次点击,则移除,不选中
viewModel.isChoice.set(false);
removeCount++;
break;
}
}
}
if (removeCount == 0) {//不是移除操作
//多选
//数量超过3个
if (choicePositions.size() >= 3) {
AppDialog.showHintDialog(activity, "最多只能选择3个职位");
viewModel.isChoice.set(false);
} else {
//添加到选中集合中
choicePositions.add(viewModel);
viewModel.isChoice.set(true);
}
}
}
//设置头上的label
setLabel();
setRootNodeSelected();
}
});
}
private void setRootNodeSelected() {
for (TreeItemViewModel itemViewModel : itemViewModels) {
//if (itemViewModel.getTreeModel().isRootNode() == 1) {
itemViewModel.isChoice.set(false);
if (choicePositions != null && choicePositions.size() > 0) {
for (TreeItemViewModel childTreeItemViewModel : choicePositions) {
if (itemViewModel.getTreeModel().getId().equals(childTreeItemViewModel.getTreeModel().getId())) {
itemViewModel.isChoice.set(true);
}
// if (itemViewModel.getTreeModel().getId().equals(childTreeItemViewModel.getTreeModel().getId())){
// itemViewModel.isChoice.set(true);
// }
}
}
// }
}
}
//设置头上的label
private void setLabel() {
int size = choicePositions.size();
if (choicePositions.size() > 0) {
if (!showLabel.get()) {
arrow.set(activity.getResources().getDrawable(R.mipmap.icon_up));
showLabel.set(!showLabel.get());
} else {
}
}
switch (size) {
case 0: {
percent.set("0");
leftVisible.set(false);
middleVisible.set(false);
rightVisible.set(false);
}
break;
case 1: {
percent.set("1");
leftVisible.set(true);
leftText.set(choicePositions.get(0).getTreeModel().getName());
middleVisible.set(false);
rightVisible.set(false);
}
break;
case 2: {
percent.set("2");
leftVisible.set(true);
middleVisible.set(true);
leftText.set(choicePositions.get(0).getTreeModel().getName());
middleText.set(choicePositions.get(1).getTreeModel().getName());
rightVisible.set(false);
}
break;
case 3: {
percent.set("3");
leftVisible.set(true);
middleVisible.set(true);
rightVisible.set(true);
leftText.set(choicePositions.get(0).getTreeModel().getName());
middleText.set(choicePositions.get(1).getTreeModel().getName());
rightText.set(choicePositions.get(2).getTreeModel().getName());
}
break;
}
}
//获取第一层数据
private void getRootNodes() {
//params.put("grade", "1");
itemViewModels.clear();
List list = new ArrayList();
for (JobBean.ResultsBean o : data) {
if (o.getGrade() == 1) {
TreeModel treeModel = new TreeModel(o, "0");
itemViewModels.add(new TreeItemViewModel(activity, treeModel));
list.add(o);
}
}
if (list.size() == 1) {
TreeModel treeModel = new TreeModel(list.get(0), "0");
Messenger.getDefault().sendToTarget(treeModel.getId(), activity);
}
//
//setRootNodeSelected();
//
}
//获取第二层数据
private void getGroupNodes(final String pid, String pname) {
List childItemViewModels=new ArrayList();
for (JobBean.ResultsBean o : data) {
if (o.getParentid()==Integer.parseInt(pid)) {
TreeModel treeModel = new TreeModel(o, pid, pname);
TreeItemViewModel itemViewModel = new TreeItemViewModel(activity, treeModel);
itemViewModel.isChoice.set(false);
childItemViewModels.add(itemViewModel);
}
}
String childId = pid;
int insertIndex = -1;
for (int i = 0; i < itemViewModels.size(); i++) {
if (itemViewModels.get(i).getTreeModel().isRootNode() == 1) {
String rootId = itemViewModels.get(i).getTreeModel().getId();
if (rootId.equals(childId)) {
insertIndex = i + 1;
}
}
}
itemViewModels.addAll(insertIndex, childItemViewModels);
if (null != choicePositions && choicePositions.size() > 0) {
setLabel();
setRootNodeSelected();
}
}
//获取第三层数据
private void getChildNodes(final String pid, final String pname) {
ArrayList childItemViewModels = new ArrayList<>();
for (JobBean.ResultsBean o : data) {
if (o.getParentid()==Integer.parseInt(pid)) {
TreeModel treeModel = new TreeModel( o, "", pname);
TreeItemViewModel itemViewModel = new TreeItemViewModel(activity, treeModel);
itemViewModel.isChoice.set(false);
if (choicePositions != null && choicePositions.size() > 0) {
for (TreeItemViewModel selectedItemViewModel : choicePositions) {
if (selectedItemViewModel.getTreeModel().getId().equals(treeModel.getId())) {
itemViewModel.isChoice.set(true);
}
}
}
childItemViewModels.add(itemViewModel);
}
}
String childId = pid;
int insertIndex = -1;
for (int i = 0; i < itemViewModels.size(); i++) {
if (itemViewModels.get(i).getTreeModel().isRootNode() ==2) {
String rootId = itemViewModels.get(i).getTreeModel().getId();
if (rootId.equals(childId)) {
insertIndex = i + 1;
}
}
}
itemViewModels.addAll(insertIndex, childItemViewModels);
if (null != choicePositions && choicePositions.size() > 0) {
setLabel();
setRootNodeSelected();
}
}
//左边点击去除选中
public final ReplyCommand leftTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
choicePositions.remove(0);
setLabel();
setRootNodeSelected();
}
});
//中间点击去重选中
public final ReplyCommand middleTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
choicePositions.remove(1);
setLabel();
setRootNodeSelected();
}
});
//右边点击去除选中
public final ReplyCommand rightTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
choicePositions.remove(2);
setLabel();
setRootNodeSelected();
}
});
@Override
public void start(String... args) {
initJosnData();
getRootNodes();
}
//初始化json数据
private void initJosnData() {
try {
StringBuffer sb = new StringBuffer();
InputStream is = activity.getAssets().open("job.json");
int len = -1;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
sb.append(new String(buf, 0, len, "utf-8"));
}
is.close();
Log.d("sdsds", sb.toString() + "hh");
Gson gson = new Gson();
JobBean bean= gson.fromJson(sb.toString(),new TypeToken() {}.getType());
for (JobBean.ResultsBean j:bean.getResults()){
data.add(j);
}
} catch (IOException e) {
e.printStackTrace();
}
}
TreeModel 每个item需要用到的数据,其中isRootNode判断是第几层
public class TreeModel implements Parcelable {
private String id;
private String pid;
private String name;
private String parentId;
private String pname;
public TreeModel(){}
public TreeModel(JobBean.ResultsBean resultsBean, String parentId) {
this.id =resultsBean.getId()+"";
this.pid = resultsBean.getParentid()+"";
this.name = resultsBean.getCategoryname();
this.parentId = parentId;
}
public TreeModel(JobBean.ResultsBean resultsBean, String parentId, String pname) {
this(resultsBean, parentId);
this.pname = pname;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public int isRootNode() {
if (parentId.equals("0")){
return 1;
}else if (pid.equals(parentId)){
return 2;
}else {
return 3;
}
// return pid.equals(parentId) ? true : false;
}
public boolean isRoot() {
return pid.equals(parentId) ? true : false;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.pid);
dest.writeString(this.name);
dest.writeString(this.parentId);
dest.writeString(this.pname);
}
protected TreeModel(Parcel in) {
this.id = in.readString();
this.pid = in.readString();
this.name = in.readString();
this.parentId = in.readString();
this.pname = in.readString();
}
public static final Creator CREATOR = new Creator() {
@Override
public TreeModel createFromParcel(Parcel source) {
return new TreeModel(source);
}
@Override
public TreeModel[] newArray(int size) {
return new TreeModel[size];
}
};
}
TreeItemViewModel 绑定 itemview
public class TreeItemViewModel {
public static final String TAG = TreeItemViewModel.class.getSimpleName();
private final ChoiceJobCategoryActivity activity;
private final TreeModel treeModel;
public final ObservableField name = new ObservableField<>();
public final ObservableBoolean isChoice = new ObservableBoolean();
public final ObservableBoolean isUnfold = new ObservableBoolean();
public TreeItemViewModel(ChoiceJobCategoryActivity activity, TreeModel treeModel) {
this.treeModel = treeModel;
this.activity = activity;
name.set(treeModel.getName());
}
public TreeModel getTreeModel() {
return treeModel;
}
//根据treemodel里面的isRootNode这个参数判断是第几层做是否展开的相关操作
public final ReplyCommand itemClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
if (treeModel.isRootNode()==1) {
isUnfold.set(!isUnfold.get());
Messenger.getDefault().sendToTarget(treeModel.getId(), activity);
} else if (treeModel.isRootNode()==2){
isUnfold.set(!isUnfold.get());
Messenger.getDefault().sendToTarget(Integer.parseInt(treeModel.getId()), activity);
}else {
Messenger.getDefault().sendToTarget(TreeItemViewModel.this, activity);
}
}
});
//根据treemodel里面的isRootNode这个参数判断是第几层做checkbox是否可以选中的相关操作
public final ReplyCommand choiceClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
if (treeModel.isRootNode()==1) {
} else if (treeModel.isRootNode()==2){
Messenger.getDefault().sendToTarget(TreeItemViewModel.this, activity);
}else {
}
}
});
}
下载代码请点击