android-Data Binding+recycleview打造二三级都可以选择的三级列表

效果图

这里写图片描述

这是前段时间做得一个项目需求,要求能够选择选择第二级和第三级的一个三级列表,话不多说了,看代码吧

一、项目配置

由于这个项目早期的框架用的是databing,关于databing的一些介绍就不写了,只是贴出来一些gradle的必要的配置
//这个是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

<?xml version="1.0" encoding="utf-8"?>
<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<TreeModel> 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<TreeItemViewModel> choicePositions = new ArrayList<>();
    private List<JobBean.ResultsBean> 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 = 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<TreeModel> choicePositions) {
        this.choicePositions.clear();
        ArrayList<TreeItemViewModel> 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<String>() {
                    @Override
                    public void call(String id) {
                        ArrayList<TreeItemViewModel> removeItems = new ArrayList<>();
                        ArrayList<TreeItemViewModel> 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<Integer>() {
            @Override
            public void call(Integer integer) {
                // ToastUtil.getInstance().show("yijind");
                ArrayList<TreeItemViewModel> 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<TreeItemViewModel>() {
            @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<JobBean.ResultsBean> list = new ArrayList<JobBean.ResultsBean>();
        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<TreeItemViewModel> childItemViewModels=new ArrayList<TreeItemViewModel>();
                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<TreeItemViewModel> 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<JobBean>() {}.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<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 = TreeItemViewModel.class.getSimpleName();
    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;
        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 {
            }
        }
    });

}

下载代码请点击

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值