列表控件:多級樹(第三方AndroidTreeView)

第三方框架AndroidTreeView官方網址Github Demo其中使用到一個 第三方圖標框架Print 。

不使用圖標庫框架Print(因爲不需要)。

分析第三方框架AndroidTreeView:

        每一層使用LinearLayout添加內部節點(TreeNodeWrapperView)。

一、實現的功能

        默認顯示所有年級名稱;點擊某一個年級,加載其所有班級名稱;點擊某一班級,加載其所有學生名稱。年級、班級單選,學生可多選。選擇的項文字變紅,沒選擇的是黑色。相應的箭頭會根據狀態改變。

二、運行效果

三、功能代碼

因爲功能需求,在library的AndroidTreeView中新增了一個方法:

   //新增函數:只展開自己;收縮自己及子節點
    public void toggleNode(TreeNode node,boolean includeSubnodes) {
        if (node.isExpanded()) {
            collapseNode(node, includeSubnodes);//收縮所有,包括子節點
        } else {
            expandNode(node, false);//只展開自己
        }

    }

Fragment代碼:

功能邏輯處理整個過程

public class MoreListFragment extends Fragment {

    private TextView tvShow;
    private ViewGroup containerView;
    private AndroidTreeView tView;

    private TreeNode choseGradeNode;//已選的年級節點
    private String choseGradeStr;//已選的年級值
    private List<TreeNode> initGradeList = new ArrayList<>();//已初始化班級節點的年級
    private TreeNode choseClassNode;//已選的班級節點
    private String choseClassStr;//已選的班級值
    private List<TreeNode> initClassList = new ArrayList<>();//已初始化學生節點的班級
    private List<String> choseStudentList = new ArrayList<>();//已選的學生值
    private int nodeCount = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_default, null, false);
        containerView = (ViewGroup) rootView.findViewById(R.id.container);
        tvShow = (TextView) rootView.findViewById(R.id.status_bar);
        initGradeNodes();
        return rootView;
    }

    /**
     * 初始化年級節點
     */
    private void initGradeNodes(){
        TreeNode root = TreeNode.root();
        for (int i = 0; i < 3; i++) {
            TreeNode areaNode = new TreeNode(new TreeNodeHolder.IconTreeItem("grade_" + i, "" + nodeCount,0));
            nodeCount++;
            root.addChildren(areaNode);
        }
        tView = new AndroidTreeView(getActivity(), root);
        tView.setDefaultAnimation(true);
        tView.setUseAutoToggle(false);//不使用自動展開收縮
        tView.setDefaultContainerStyle(R.style.TreeNodeStyleCustom);//TreeNodeStyleCustom、 TreeNodeStyleDivided
        tView.setDefaultViewHolder(TreeNodeHolder.class);
        tView.setDefaultNodeClickListener(nodeClickListener);

        containerView.addView(tView.getView());
    }

    /**
     * 初始化指定班級節點下的所有班級節點
     * @param gradeNode 年級節點
     */
    private void initClassNodes(TreeNode gradeNode){
        for (int j = 0; j < 3; j++) {
            TreeNode classNode = new TreeNode(new TreeNodeHolder.IconTreeItem("class_" + j, "" + nodeCount,1));
            nodeCount++;
            tView.addNode(gradeNode,classNode);
        }
        initGradeList.add(gradeNode);
    }

    /**
     * 初始化指定班級節點下的所有學生節點
     * @param classNode 班級節點
     */
    private void initStudentNodes(TreeNode classNode){
        for (int j = 0; j < 3; j++) {
            TreeNode studentNode = new TreeNode(new TreeNodeHolder.IconTreeItem("student_" + j, "" + nodeCount,2));
            nodeCount++;
            tView.addNode(classNode,studentNode);
        }
        initClassList.add(classNode);
    }

    /**
     * 多級樹節點點擊事件
     */
    private TreeNode.TreeNodeClickListener nodeClickListener = new TreeNode.TreeNodeClickListener() {
        @Override
        public void onClick(TreeNode node, Object value) {
            TreeNodeHolder.IconTreeItem item = (TreeNodeHolder.IconTreeItem) value;
            switch (item.level){
                case 0:
                    choseClassNode = null;
                    choseClassStr = "";
                    choseStudentList.clear();
                    if (choseGradeNode != null){//之前已選過節點
                        TreeNodeHolder.IconTreeItem choseAreaNodeValue = (TreeNodeHolder.IconTreeItem) choseGradeNode.getValue();
                        if (!item.id.equals(choseAreaNodeValue.id)) {
                            //此節點 != 上次選擇的節點,則取消、收縮上次的節點及其子節點
                            tView.toggleNode(choseGradeNode, true);
                        }
                    }
                    choseGradeNode = node;
                    tView.toggleNode(node, true);//只展開此節點或收縮此節點及其子節點
                    if(node.isExpanded()){//選擇此節點
                        choseGradeStr = item.text;
                        if(!initGradeList.contains(node)){//此節點還未初始化過子節點
                            initClassNodes(node);
                        }
                    }else {//取消此節點
                        choseGradeStr = "";
                        choseGradeNode = null;
                    }
                    break;
                case 1:
                    choseStudentList.clear();
                    if (choseClassNode != null){//之前已選過節點
                        TreeNodeHolder.IconTreeItem choseHspNodeValue = (TreeNodeHolder.IconTreeItem) choseClassNode.getValue();
                        if (!item.id.equals(choseHspNodeValue.id)) {
                            //此節點 != 上次選擇的節點,則取消、收縮上次的節點
                            tView.toggleNode(choseClassNode, true);
                        }
                    }
                    choseClassNode = node;
                    tView.toggleNode(node, true);//只展開此節點或收縮此節點及其子節點
                    if(node.isExpanded()){//選擇此節點
                        choseClassStr = item.text;
                        if(!initClassList.contains(node)){//此節點還未初始化過子節點
                            initStudentNodes(node);
                        }
                    }else {//取消此節點
                        choseClassStr = "";
                        choseClassNode = null;
                    }
                    break;
                case 2:
                    if(!choseStudentList.contains(item.text)){
                        choseStudentList.add(item.text);
                    }else {
                        choseStudentList.remove(item.text);
                    }
                    tView.toggleNode(node, true);
                    break;
            }
            tvShow.setText("["+choseGradeStr+"]_["+choseClassStr+"]_"+choseStudentList.toString());
        }
    };
}

ViewHolder:

public class TreeNodeHolder extends TreeNode.BaseNodeViewHolder<TreeNodeHolder.IconTreeItem> {

    private TextView tvValue;
    private ImageView ivArrowIcon;

    public TreeNodeHolder(Context context) {
        super(context);
    }

    @Override
    public View createNodeView(final TreeNode node, final IconTreeItem value) {
        final LayoutInflater inflater = LayoutInflater.from(context);
        final View view = inflater.inflate(R.layout.item_tree_node, null, false);
        tvValue = (TextView) view.findViewById(R.id.node_value);
        tvValue.setText(value.text);
        ivArrowIcon = (ImageView) view.findViewById(R.id.iv_arrow_icon);
        if (value.level == 2) {
            ivArrowIcon.setVisibility(View.GONE);
        }
        return view;
    }

    @Override
    public void toggle(boolean active) {
        ivArrowIcon.setImageDrawable(context.getResources().getDrawable(active ? R.mipmap.ic_node_open:R.mipmap.ic_node_close));
        tvValue.setTextColor(context.getResources().getColor(active ? R.color.text_red : R.color.text_black));
    }

    public static class IconTreeItem {
        public String text;//文字
        public String id;
        public int level;

        public IconTreeItem(String text,String id,int level) {
            this.text = text;
            this.id = id;
            this.level = level;
        }
    }
}

fragment的佈局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:padding="8dp"
        android:textSize="16sp"
        android:text="Last Clicked:"
        android:layout_alignParentTop="true"
        android:background="@android:color/holo_blue_dark"
        android:id="@+id/status_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <RelativeLayout
        android:layout_below="@id/status_bar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/container"></RelativeLayout>


</RelativeLayout>

item的佈局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:minHeight="48dp"
    android:gravity="center_vertical"
    android:background="?android:attr/selectableItemBackground"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_arrow_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:gravity="center"
            android:src="@mipmap/ic_node_close"
            android:scaleType="centerInside"/>
        <TextView
            android:textSize="16sp"
            android:layout_marginLeft="10dp"
            android:id="@+id/node_value"
            android:textColor="@color/text_black"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</RelativeLayout>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章