自定义AndroidTreeView设置支持全选后不勾选某一个,上一级全选不勾选

Android 树形结构(AndroidTreeView)github地址:https://github.com/bmelnychuk/AndroidTreeView

引入方式:implementation 'com.github.bmelnychuk:atv:1.2.+'
具体使用请移步github官网

跑了官网的例子,发现父节点勾选后子节点会全部选中,父节点取消勾选后子节点也会全部取消选中

自定义AndroidTreeView设置支持全选后不勾选某一个,上一级全选不勾选_第1张图片

但是在父节点勾选后子节点全部选中的情况下,点击一个子节点不勾选,这时父节点没有取消勾选,居于这种(类似于删除文件有一个没选即不能为全选)使用场景,修改AndroidTreeView项目相关源码

修改主要为ArrowExpandSelectableHeaderHolder.java类

public class ArrowExpandSelectableHeaderHolder extends TreeNode.BaseNodeViewHolder {
    private TextView tvValue;
    private PrintView arrowView;
    private CheckBox nodeSelector;

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

    @Override
    public View createNodeView(final TreeNode node, ArrowExpandSelectableHeaderHolder.IconTreeItem value) {
        final LayoutInflater inflater = LayoutInflater.from(context);
        final View view = inflater.inflate(R.layout.layout_selectable_header, null, false);

        tvValue = (TextView) view.findViewById(R.id.node_value);
        tvValue.setText(value.text);

        final PrintView iconView = (PrintView) view.findViewById(R.id.icon);
        iconView.setIconText(context.getResources().getString(value.icon));

        arrowView = (PrintView) view.findViewById(R.id.arrow_icon);
        arrowView.setPadding(20,10,10,10);
        if (node.isLeaf()) {
            arrowView.setVisibility(View.GONE);
        }
        arrowView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tView.toggleNode(node);
            }
        });

        nodeSelector = (CheckBox) view.findViewById(R.id.node_selector);
        nodeSelector.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                node.setSelected(isChecked);
                for (TreeNode n : node.getChildren()) {
                    getTreeView().selectNode(n, isChecked);
                }
            }
        });
        nodeSelector.setChecked(node.isSelected());

        return view;
    }

    @Override
    public void toggle(boolean active) {
        arrowView.setIconText(context.getResources().getString(active ? R.string.ic_keyboard_arrow_down : R.string.ic_keyboard_arrow_right));
    }

    @Override
    public void toggleSelectionMode(boolean editModeEnabled) {
        nodeSelector.setVisibility(editModeEnabled ? View.VISIBLE : View.GONE);
        nodeSelector.setChecked(mNode.isSelected());
    }

    public static class IconTreeItem {
        public int icon;
        public String text;

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

}

这个类中CheckBox设置setOnCheckedChangeListener监听,如果父节点用node.getParent(),然后调用getTreeView().selectNode(n, isChecked)

最后会导致调用toggleSelectionMode方法

@Override
    public void toggleSelectionMode(boolean editModeEnabled) {
        nodeSelector.setVisibility(editModeEnabled ? View.VISIBLE : View.GONE);
        nodeSelector.setChecked(mNode.isSelected());
    }

调用toggleSelectionMode就会调用setChecked,调用setChecked会再调用setOnCheckedChangeListener

这样的代码实现就会表现为 点击不勾选某一个子节点后,这个父节点和所有子节点都取消了选中

下面对此处代码进行修改,以实现本文开始处要实现的使用场景,修改的还是ArrowExpandSelectableHeaderHolder.java类

public class ArrowExpandSelectableHolder extends TreeNode.BaseNodeViewHolder {
    private TextView tvValue;
    private ImageView arrowView;
    private CheckBox nodeSelector;

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

    @Override
    public View createNodeView(final TreeNode node, ArrowExpandSelectableHolder.IconTreeItem value) {
        final LayoutInflater inflater = LayoutInflater.from(context);
        final View view = inflater.inflate(R.layout.layout_selectable_header, null, false);

        tvValue = (TextView) view.findViewById(R.id.node_value);
        tvValue.setText(value.text);

        arrowView = (ImageView) view.findViewById(R.id.arrow_icon);
        arrowView.setPadding(20, 10, 10, 10);
        if (value.type.equals("3")) {
            arrowView.setVisibility(View.GONE);
        }
        arrowView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tView.toggleNode(node);
            }
        });

        nodeSelector = (CheckBox) view.findViewById(R.id.node_selector);
        nodeSelector.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                node.setSelected(nodeSelector.isChecked());
                setChildChecked(node, nodeSelector.isChecked());
                if (node.getParent() != null)
                    setNodeParentChecked(node.getParent(), nodeSelector.isChecked());
            }
        });
        nodeSelector.setChecked(node.isSelected());

        return view;
    }

    @Override
    public void toggle(boolean active) {
        if (active) {
            arrowView.setBackgroundResource(R.mipmap.down_arrow);
        } else {
            arrowView.setBackgroundResource(R.mipmap.right_arrow);
        }
    }

    @Override
    public void toggleSelectionMode(boolean editModeEnabled) {
        nodeSelector.setVisibility(editModeEnabled ? View.VISIBLE : View.GONE);
        nodeSelector.setChecked(mNode.isSelected());
    }

    /**
     * 设置是否选中
     *
     * @param node
     * @param checked
     */
    public void setChildChecked(TreeNode node, boolean checked) {
        if (!node.isLeaf()) {
            getTreeView().selectNode(node, checked);
            for (TreeNode childrenNode : node.getChildren()) {
                setChildChecked(childrenNode, checked);
            }
        } else {
            getTreeView().selectNode(node, checked);
        }
    }


    private void setNodeParentChecked(TreeNode node, boolean checked) {
        if (checked) {
            List childrens = node.getChildren();
            int i = 0;
            for (TreeNode children : childrens) {
                if (children.isSelected()) {
                    i++;
                }
            }
            //如果所有自节点都没有被选中 父节点也不选中
            if (i == childrens.size()) {
                getTreeView().selectNode(node, checked);
            }
            if (node.getParent() != null)
                setNodeParentChecked(node.getParent(), checked);
        } else {
            getTreeView().selectNode(node, checked);
            if (node.getParent() != null)
                setNodeParentChecked(node.getParent(), checked);
        }
    }

    public static class IconTreeItem {
        public String id;
        public String text;
        public String type;

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

}

仔细观察会发现,我将setOnCheckedChangeListener监听,修改为setOnClickListener监听,同时也对子节点和父节点分别进行勾选与不勾选的判断处理,这样就避免了上文的情况的发生。

希望有需要的朋友可以帮到你们,如有不对之处,烦请留言指正谢谢!

你可能感兴趣的:(AndroidTreeView,树形结构,Android)