效果图
这是前段时间做得一个项目需求,要求能够选择选择第二级和第三级的一个三级列表,话不多说了,看代码吧
一、项目配置
由于这个项目早期的框架用的是databing,关于databing的一些介绍就不写了,只是贴出来一些gradle的必要的配置
//这个是databing的
android {
dataBinding {
enabled = true
}
}
//这是用到的依赖包,个人习惯,可以根据自己的方式调整
compile ':rxjava:1.2.4'
compile ':rxandroid:1.2.1'
compile ':library:1.0.0'
//一个Android MVVM 轻量级工具库,里面添加了一些Data Binding 不支持的属性,还有添加对控件事件的封装,同时提个一个全局消息通道方便ViewModel 之间的通信,Toolkit主要包括两部分Binding和Messenger
compile ':gson:2.2.4'//用来解析json的
二、代码和布局
activity_choice_job_category.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="/apk/res/android"
xmlns:bind="/apk/res-auto"
xmlns:tools="/tools">
<data>
<import type="" />
<import type="" />
<variable
name="viewModel"
type="" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="">
<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="@{ ? : }">
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{}"
bind:clickCommand="@{}"
android:visibility="@{ ? : }" />
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{}"
bind:clickCommand="@{}"
android:visibility="@{ ? : }" />
<TextView
style="@style/textStyle"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@{}"
bind:clickCommand="@{}"
android:visibility="@{ ? : }" />
</LinearLayout>
<.
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:itemView="@{}"
bind:items="@{}"
bind:layoutManager="@{()}" />
</LinearLayout>
</layout>
Data Binding的好处,直接用精简的代码实现数据与UI和逻辑的绑定,不需要编写大量的毫无营养繁琐的的代码,如 findViewById()、setText(),setVisibility(),setEnabled() 或 setOnClickListener() 等通通不需要
public class ChoiceJobCategoryActivity extends AppCompatActivity {
private ActivityChoiceJobCategoryBinding binding;//这个是自动生成滴
private JobCategoryViewModel viewModel;
private ArrayList<TreeModel> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new JobCategoryViewModel(this);
//前面带过来已选中的数据
list = getIntent().getParcelableArrayListExtra("selected");
if (list != null) {
(list);
}
binding = (this, .activity_choice_job_category);
(viewModel);
();
}
public void initLayout() {
().notifyDataSetChanged();
}
@Override
protected void onDestroy() {
super.onDestroy();
().unregister(this);
}
}
这个页面实际上是一个过渡页面,起到一个桥梁的作用,实现activity与布局的绑定,主要的逻辑在viewmodel里面去实现
恩,下面才是重头戏
JobCategoryViewModel
public class JobCategoryViewModel extends BaseViewModel {
public static final String TAG = ();
public static final String EXTRA_SINGLE = "single";
private ChoiceJobCategoryActivity activity;
private boolean isSingle;
private ArrayList<TreeItemViewModel> choicePositions = new ArrayList<>();
private List<> data = new ArrayList<>();
private ArrayList<TreeModel> choicePositionsValues = new ArrayList<>();
public final ObservableList<TreeItemViewModel> itemViewModels = new ObservableArrayList<>();
public final ObservableList<TreeItemViewModel> childItemViewModels = new ObservableArrayList<>();
public final ObservableField<Drawable> 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<String> leftText = new ObservableField<>();
public final ObservableField<String> middleText = new ObservableField<>();
public final ObservableField<String> rightText = new ObservableField<>();
public final ObservableField<String> tot alCount = new ObservableField<>();
public final ObservableField<String> percent = new ObservableField<>("0");
//三级列表分不同的布局,分别是case1,2,3
public final ItemViewSelector<TreeItemViewModel> itemView = new ItemViewSelector<TreeItemViewModel>() {
@Override
public void select(ItemView itemView, int position, TreeItemViewModel item) {
int itemType = ().isRootNode();
switch (itemType) {
case 1:
itemView.set(, .item_tree_group);
break;
case 2:
itemView.set(, .item_tree_root);
break;
case 3:
itemView.set(, .item_tree_leaf);
break;
}
}
@Override
public int viewTypeCount() {
return 3;
}
};
//初始化上次选中的页面
public void setChoicePositions(ArrayList<TreeModel> choicePositions) {
this.();
ArrayList<TreeItemViewModel> choiceItemViewModels = new ArrayList<>();
for (TreeModel treeModel : choicePositions) {
(new TreeItemViewModel(activity, treeModel));
}
this.(choiceItemViewModels);
percent.set(() + "");
setLabel();
}
//初始化数据
public JobCategoryViewModel(final ChoiceJobCategoryActivity activity) {
this.activity = activity;
isSingle = ().getBooleanExtra(EXTRA_SINGLE, false);
arrow.set(().getDrawable(.icon_down));
//监听treeitemviewmodel一级列表的展开
().register(activity, , new Action1<String>() {
@Override
public void call(String id) {
ArrayList<TreeItemViewModel> removeItems = new ArrayList<>();
ArrayList<TreeItemViewModel> removechildItems = new ArrayList<>();
for (TreeItemViewModel itemViewModel : itemViewModels) {
if (().getPid().equals(id)) {
(itemViewModel);
}
for (TreeItemViewModel childitemViewModel : itemViewModels) {
if (().getPid().equals(().getId())) {
(childitemViewModel);
}
}
}
if (() > 0) {
(removeItems);
(removechildItems);
();
} else {
getGroupNodes(id, "");
}
();
();
}
}
);
//监听treeitemviewmodel 二级列表的展开
().register(activity, , new Action1<Integer>() {
@Override
public void call(Integer integer) {
// ().show("yijind");
ArrayList<TreeItemViewModel> removeItems = new ArrayList<>();
for (TreeItemViewModel itemViewModel : itemViewModels) {
if (().getPid().equals(integer + "")) {
(itemViewModel);
}
}
if (() > 0) {
(removeItems);
();
} else {
getChildNodes(integer + "", "");
}
();
}
});
//监听treeitemviewmodel二级和一级 checkbox的选中和移除
().register(activity, , new Action1<TreeItemViewModel>() {
@Override
public void call(TreeItemViewModel viewModel) {
int removeCount = 0;
if (isSingle) {//单选---->回绑已ok
();
if (itemViewModels != null && () > 0) {
for (int i = 0; i < (); i++) {
itemViewModels.get(i).isChoice.set(false);
}
}
.set(true);
(viewModel);
} else {
if (choicePositions != null && () > 0) {
for (int i = 0; i < (); i++) {
TreeItemViewModel item = choicePositions.get(i);
if (().getId().equals(().getId())) {
(i);//已经选过了,再次点击,则移除,不选中
.set(false);
removeCount++;
break;
}
}
}
if (removeCount == 0) {//不是移除操作
//多选
//数量超过3个
if (() >= 3) {
(activity, "最多只能选择3个职位");
.set(false);
} else {
//添加到选中集合中
(viewModel);
.set(true);
}
}
}
//设置头上的label
setLabel();
setRootNodeSelected();
}
});
}
private void setRootNodeSelected() {
for (TreeItemViewModel itemViewModel : itemViewModels) {
//if (().isRootNode() == 1) {
.set(false);
if (choicePositions != null && () > 0) {
for (TreeItemViewModel childTreeItemViewModel : choicePositions) {
if (().getId().equals(().getId())) {
.set(true);
}
// if (().getId().equals(().getId())){
// (true);
// }
}
}
// }
}
}
//设置头上的label
private void setLabel() {
int size = ();
if (() > 0) {
if (!showLabel.get()) {
arrow.set(().getDrawable(.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() {
//("grade", "1");
();
List<> list = new ArrayList<>();
for ( o : data) {
if (() == 1) {
TreeModel treeModel = new TreeModel(o, "0");
(new TreeItemViewModel(activity, treeModel));
(o);
}
}
if (() == 1) {
TreeModel treeModel = new TreeModel(list.get(0), "0");
().sendToTarget((), activity);
}
//
//setRootNodeSelected();
//
}
//获取第二层数据
private void getGroupNodes(final String pid, String pname) {
List<TreeItemViewModel> childItemViewModels=new ArrayList<TreeItemViewModel>();
for ( o : data) {
if (()==(pid)) {
TreeModel treeModel = new TreeModel(o, pid, pname);
TreeItemViewModel itemViewModel = new TreeItemViewModel(activity, treeModel);
.set(false);
(itemViewModel);
}
}
String childId = pid;
int insertIndex = -1;
for (int i = 0; i < (); i++) {
if (itemViewModels.get(i).getTreeModel().isRootNode() == 1) {
String rootId = itemViewModels.get(i).getTreeModel().getId();
if ((childId)) {
insertIndex = i + 1;
}
}
}
(insertIndex, childItemViewModels);
if (null != choicePositions && () > 0) {
setLabel();
setRootNodeSelected();
}
}
//获取第三层数据
private void getChildNodes(final String pid, final String pname) {
ArrayList<TreeItemViewModel> childItemViewModels = new ArrayList<>();
for ( o : data) {
if (()==(pid)) {
TreeModel treeModel = new TreeModel( o, "", pname);
TreeItemViewModel itemViewModel = new TreeItemViewModel(activity, treeModel);
.set(false);
if (choicePositions != null && () > 0) {
for (TreeItemViewModel selectedItemViewModel : choicePositions) {
if (().getId().equals(())) {
.set(true);
}
}
}
(itemViewModel);
}
}
String childId = pid;
int insertIndex = -1;
for (int i = 0; i < (); i++) {
if (itemViewModels.get(i).getTreeModel().isRootNode() ==2) {
String rootId = itemViewModels.get(i).getTreeModel().getId();
if ((childId)) {
insertIndex = i + 1;
}
}
}
(insertIndex, childItemViewModels);
if (null != choicePositions && () > 0) {
setLabel();
setRootNodeSelected();
}
}
//左边点击去除选中
public final ReplyCommand leftTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
(0);
setLabel();
setRootNodeSelected();
}
});
//中间点击去重选中
public final ReplyCommand middleTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
(1);
setLabel();
setRootNodeSelected();
}
});
//右边点击去除选中
public final ReplyCommand rightTextClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
(2);
setLabel();
setRootNodeSelected();
}
});
@Override
public void start(String... args) {
initJosnData();
getRootNodes();
}
//初始化json数据
private void initJosnData() {
try {
StringBuffer sb = new StringBuffer();
InputStream is = ().open("");
int len = -1;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
(new String(buf, 0, len, "utf-8"));
}
is.close();
("sdsds", () + "hh");
Gson gson = new Gson();
JobBean bean= ((),new TypeToken<JobBean>() {}.getType());
for ( j:()){
(j);
}
} catch (IOException e) {
();
}
}
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( resultsBean, String parentId) {
this.id =()+"";
this.pid = ()+"";
this.name = ();
this.parentId = parentId;
}
public TreeModel( 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 (("0")){
return 1;
}else if ((parentId)){
return 2;
}else {
return 3;
}
// return (parentId) ? true : false;
}
public boolean isRoot() {
return (parentId) ? true : false;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
(this.id);
(this.pid);
(this.name);
(this.parentId);
(this.pname);
}
protected TreeModel(Parcel in) {
this.id = ();
this.pid = ();
this.name = ();
this.parentId = ();
this.pname = ();
}
public static final Creator<TreeModel> CREATOR = new Creator<TreeModel>() {
@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 = ();
private final ChoiceJobCategoryActivity activity;
private final TreeModel treeModel;
public final ObservableField<String> 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;
(());
}
public TreeModel getTreeModel() {
return treeModel;
}
//根据treemodel里面的isRootNode这个参数判断是第几层做是否展开的相关操作
public final ReplyCommand itemClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
if (()==1) {
(!());
().sendToTarget((), activity);
} else if (()==2){
(!());
().sendToTarget((()), activity);
}else {
().sendToTarget(TreeItemViewModel.this, activity);
}
}
});
//根据treemodel里面的isRootNode这个参数判断是第几层做checkbox是否可以选中的相关操作
public final ReplyCommand choiceClickCommand = new ReplyCommand(new Action0() {
@Override
public void call() {
if (()==1) {
} else if (()==2){
().sendToTarget(TreeItemViewModel.this, activity);
}else {
}
}
});
}
下载代码请点击