树型视图构建

UI视图

效果如下
在这里插入图片描述

以下是展示树型视图的xml文件和dialog界面

public class DataCollectCreateAreaDialog extends DataCollectBaseDialog {

    private RelativeLayout rlArea;
    @BindView(R.id.btn_data_collect_area_confirm)
    Button btnConfirm;

    private Map<String, Object> returnMap;
    private List<Integer> addressIdList;
    private List<String> saveNodeNameList;
    private TreeNode root;
    private TreeNode treeNode;
    private TreeNode childTreeNode;
    private TreeView treeView;

    @SuppressLint("LongLogTag")
    private void initView() {
        rlArea = view.findViewById(R.id.rl_area);

        root = TreeNode.root();
        returnMap=new HashMap<>();
        addressIdList = new ArrayList<>();
        saveNodeNameList = new ArrayList<>();
        AreaTreeCheckBoxUtil util = new AreaTreeCheckBoxUtil(context, rlArea);

        ((Toolbar) view.findViewById(R.id.toolbar)).setNavigationOnClickListener(v -> cancelOn());

        btnConfirm.setOnClickListener(v1 -> {
            saveNodeNameList.clear();
            addressIdList.clear();

            util.getData();

            addressIdList = util.getSaveIdList();
            saveNodeNameList = util.getSaveNodeNameList();

            Log.d(TAG, " -=-=- initView: addressIdList:" + addressIdList);
            Log.d(TAG, " -=-=- initView: saveNodeNameList:" + saveNodeNameList);

            StringBuilder addressId = new StringBuilder();
            StringBuilder sbName = new StringBuilder();

            for (Integer integer : addressIdList) addressId.append(integer).append(";");
            for (String s : saveNodeNameList) sbName.append(s).append(";");

            Log.d(TAG, " -=-=- initView: sbName:" + sbName.toString());

            if (TextUtils.isEmpty(sbName.toString())) showToast("请选择区域!");
            else {
                returnMap.put("addressName", sbName.subSequence(0, sbName.length() - 1));
                if (!TextUtils.isEmpty(addressId.toString()))
                    returnMap.put("addressId", addressId.subSequence(0, addressId.length() - 1));

                returnData();
                cancelOn();
            }
        });
        show();
    }
    ...
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/new_broad_details_bg"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:title="选择区域"
        app:titleTextColor="@color/c_ffffff"
        app:layout_constraintTop_toTopOf="parent"
        app:navigationIcon="@drawable/ic_back_white_24" />

    <RelativeLayout
        android:id="@+id/rl_area"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn_data_collect_area_confirm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/c_4791ff"
        android:text="@string/filtrateFinish"
        android:textColor="@color/c_ffffff" />

</LinearLayout>

构造树型结构数据

AreaTreeCheckBoxUtil是构造树型结构数据的工具类,负责获取所有区域数据、构造树型结构数据

public class AreaTreeCheckBoxUtil {

    private TreeNode root;
    private TreeNode treeNode;
    private TreeNode childTreeNode;
    private TreeView treeView;

    public List<Integer> saveIdList;
    public List<String> saveNodeNameList;
    private Map<Integer, Integer> hierarchyMap;

    private Context context;
    private RelativeLayout rlArea;
    int nodeHierarchy;

    public AreaTreeCheckBoxUtil(Context context, RelativeLayout rlArea) {
        this.context = context;
        this.rlArea = rlArea;
        nodeHierarchy = 1;
        initTree();
    }

    @SuppressLint("LongLogTag")
    private void initTree() {
        root = TreeNode.root();
        saveIdList = new ArrayList<>(); // 保存区域id
        saveNodeNameList = new ArrayList<>(); // 保存每个区域节点名称
        hierarchyMap = new HashMap<>();

        int id = SPUtils.getInstance().getInt(SpConfig.PermissionId);
        String level = SPUtils.getInstance().getString(SpConfig.PermissionLevel);

        // 请求所有区域的数据
        DataCollectModel.roleAreaTree(id, level, (isSuccess,o) -> {
            AreaEntity areaEntity = (AreaEntity) o;
            Log.d("DataCollectCreateAreaDialog", " -=-=- initView: areaEntity:" + areaEntity);
            System.out.println(" -=-=-=- initView: areaEntity:" + areaEntity);
            if (areaEntity != null) {
                initAreaData(areaEntity); // 构造树型结构数据
                createNodeViewFactory(); // 将树型结构数据按父子等级存入map
                initNodeView(); // 创建树型节点视图
            }
        });
    }

    private void initAreaData(AreaEntity areaEntity) {
        for (AreaEntity.ReturnDataBean returnDatum : areaEntity.getReturnData()) {
            treeNode = createTreeNode(returnDatum.getText(), returnDatum.getId(),
                    returnDatum.getParentId(), returnDatum.getAddressLevel());
            root.addChild(treeNode);
            if (!returnDatum.getChildren().isEmpty()) getChildArea(returnDatum, treeNode);
        }
    }

    // 使用递归算法遍历每个子节点,将原始数据构造成树型数据结构
    private void getChildArea(AreaEntity.ReturnDataBean child, TreeNode treeNode) {
        for (AreaEntity.ReturnDataBean childBean : child.getChildren()) {
            childTreeNode = createTreeNode(childBean.getText(), childBean.getId(),
                    childBean.getParentId(), childBean.getAddressLevel());
            treeNode.addChild(childTreeNode);
            if (!childBean.getChildren().isEmpty()) getChildArea(childBean, childTreeNode);
        }
    }

    private TreeNode createTreeNode(String text, String addressId, String paranId, String addressLevel) {
        TreeNode treeNode = new TreeNode(text);
        treeNode.setAddressId(Integer.valueOf(addressId));
        treeNode.setLevel(Integer.valueOf(paranId));
        treeNode.setAddressLevel(addressLevel);
        return treeNode;
    }

    private void initNodeView() {
        treeView = new TreeView(root, context, new NodeViewFactory(context, hierarchyMap)
                .setCallBack((expand, treeNode) -> {
                    Log.d("BroadCreateAreaDialog", " -=-=- onClick: id:" + treeNode.getAddressId());
                    Log.d("BroadCreateAreaDialog", " -=-=- onClick: level:" + treeNode.getLevel());
                }));
        View view = treeView.getView();
        view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        rlArea.addView(view);
    }


    private void createNodeViewFactory() {
        for (TreeNode treeNode : root.getChildren()) {
            hierarchyMap.put(treeNode.getLevel(), 1);
            for (TreeNode treeNode1 : treeNode.getChildren()) {
                hierarchyMap.put(treeNode1.getLevel(), 2);
                for (TreeNode treeNode2 : treeNode1.getChildren()) {
                    hierarchyMap.put(treeNode2.getLevel(), 3);
                    for (TreeNode treeNode3 : treeNode2.getChildren()) {
                        hierarchyMap.put(treeNode3.getLevel(), 4);
                        for (TreeNode treeNode4 : treeNode3.getChildren()) {
                            hierarchyMap.put(treeNode4.getLevel(), 5);
                        }
                    }
                }
            }
        }
    }

    // 获取当前选中的区域节点数据
    public void getData() {
        saveIdList.clear();
        saveNodeNameList.clear();
        for (TreeNode treeNode : root.getChildren()) {
            if (treeNode.isSelected()) {
                saveIdList.add(treeNode.getAddressId());
                saveNodeNameList.add(treeNode.getValue() + "");
            } else getData(treeNode);
        }
    }

    private void getData(TreeNode node) {
        for (TreeNode treeNode : node.getChildren()) {
            if (treeNode.isSelected()) {
                saveIdList.add(treeNode.getAddressId());
                saveNodeNameList.add(treeNode.getValue() + "");
            } else getData(treeNode);
        }
    }

    public List<String> getSaveNodeNameList() {
        getData();
        return saveNodeNameList;
    }

    public List<Integer> getSaveIdList() {
        getData();
        return saveIdList;
    }

}

节点视图

NodeViewFactory管理节点视图

public class NodeViewFactory extends BaseNodeViewFactory {

    private static final String TAG = "NodeViewFactory";

    private Context context;
    private Map<Integer, Integer> hierarchyMap;

    private NodeViewBinder.ClickCallBack callBack;

    public NodeViewFactory setCallBack(NodeViewBinder.ClickCallBack callBack) {
        this.callBack = callBack;
        return this;
    }

    CheckBoxClickListener listener;

    public interface CheckBoxClickListener {
        void clickListener(TreeNode treeNode);
    }

    public NodeViewFactory setListener(CheckBoxClickListener listener) {
        this.listener = listener;
        return this;
    }

    public NodeViewFactory(Context context, Map<Integer, Integer> hierarchyMap) {
        this.context = context;
        this.hierarchyMap = hierarchyMap;
    }

    @Override
    public BaseNodeViewBinder getNodeViewBinder(View view, int level) {
        Log.d(TAG, " -=-=- getNodeViewBinder: level:" + level);
        int hierarchy = hierarchyMap.get(level);
        Log.d(TAG, " -=-=- getNodeViewBinder: level:" + level + "  hierarchy:" + hierarchy);
        float density = context.getResources().getDisplayMetrics().density;
        int nodeHeight;
        int nodeLeftPadding;
        int leftPaddingDatum = 10;

        nodeHeight = (int) (40 * density);
        nodeLeftPadding = (int) (leftPaddingDatum * hierarchy * density);
        return getBaseNodeViewBinder(view, nodeHeight, nodeLeftPadding, View.VISIBLE);
    }

    @Override
    public void checkBoxClickListener(TreeNode treeNode) {
        if (listener != null) listener.clickListener(treeNode);
    }

    private BaseNodeViewBinder getBaseNodeViewBinder(View view, int nodeHeight, int nodeLeftPadding, int visible) {
        return new NodeViewBinder(context, view).setNodeBgColor(R.color.c_1B2F36)
                .setNodeHeight(nodeHeight).setNodeLeftPadding(nodeLeftPadding)
                .setNodeIconVisibility(visible).setCallBack(callBack).setNodeTextColor(R.color.c_ffffff);
    }

}

NodeViewBinder节点视图的显示样式

public class NodeViewBinder extends CheckableNodeViewBinder {

    private static final String TAG = "NodeViewBinder";

    private Context context;
    private TextView textView;
    private ImageView imageView;
    private RelativeLayout relativeLayout;
    private LinearLayout linearLayout;

    ClickCallBack callBack;

    public interface ClickCallBack {
        void onClick(boolean expand, TreeNode treeNode);
    }

    public NodeViewBinder setCallBack(ClickCallBack callBack) {
        this.callBack = callBack;
        return this;
    }

    public NodeViewBinder(Context context, View itemView) {
        super(itemView);
        this.context = context;
        relativeLayout = itemView.findViewById(R.id.rl_node_root_layout);
        linearLayout = itemView.findViewById(R.id.node_container);
        imageView = itemView.findViewById(R.id.arrow_img);
        textView = itemView.findViewById(R.id.node_name_view);
    }

    @Override
    public int getCheckableViewId() {
        return R.id.checkBox;
    }

    @Override
    public int getLayoutId() {
        return R.layout.node_item_level;
    }

    @Override
    public void bindView(final TreeNode treeNode) {
//        Log.d(TAG, " -=-=- bindView: treeNode:" + treeNode.getValue());
        textView.setText(treeNode.getValue() + "");
        imageView.setRotation(treeNode.isExpanded() ? 90 : 0);
        imageView.setVisibility(treeNode.hasChild() ? View.VISIBLE : View.INVISIBLE);
    }

    @Override
    public void onNodeToggled(TreeNode treeNode, boolean expand) {
        if (expand) {
            imageView.animate().rotation(90).setDuration(200).start();
        } else {
            imageView.animate().rotation(0).setDuration(200).start();
        }
        callBack.onClick(expand, treeNode);
    }

    public NodeViewBinder setNodeIcon(int iconId) {
        if (imageView != null) {
            imageView.setImageResource(iconId);
        }
        return this;
    }

    public NodeViewBinder setNodeIconVisibility(int visibility) {
        if (imageView != null) {
            imageView.setVisibility(visibility);
        }
        return this;
    }

    public NodeViewBinder setNodeHeight(int dp) {
        if (linearLayout != null) {
            ViewGroup.LayoutParams layoutParams = linearLayout.getLayoutParams();
            layoutParams.height = dp;
            linearLayout.setLayoutParams(layoutParams);
        }
        return this;
    }

    public NodeViewBinder setNodeLeftPadding(int dp) {
        if (linearLayout != null) {
            linearLayout.setPadding(dp, 0, 0, 0);
        }
        return this;
    }

    public NodeViewBinder setNodeBgColor(int colorId) {
        if (relativeLayout != null) {
            relativeLayout.setBackgroundColor(context.getResources().getColor(colorId));
        }
        return this;
    }

    public NodeViewBinder setNodeTextColor(int colorId) {
        if (relativeLayout != null) {
            textView.setTextColor(context.getResources().getColor(colorId));
        }
        return this;
    }

    @Override
    public void checkBoxClickListener(boolean expand, TreeNode treeNode) {
//        if (callBack != null) callBack.onClick(expand,treeNode);
    }

}

树视图

TreeView显示树型图

public class TreeView implements SelectableTreeAction {
    private TreeNode root;

    private Context context;

    private BaseNodeViewFactory baseNodeViewFactory;

    private RecyclerView rootView;

    private TreeViewAdapter adapter;

    private boolean itemSelectable = true;

    public void setItemAnimator(RecyclerView.ItemAnimator itemAnimator) {
        this.itemAnimator = itemAnimator;
        if (rootView != null && itemAnimator != null) {
            rootView.setItemAnimator(itemAnimator);
        }
    }

    private RecyclerView.ItemAnimator itemAnimator;

    public TreeView(@NonNull TreeNode root, @NonNull Context context, @NonNull BaseNodeViewFactory baseNodeViewFactory) {
        this.root = root;
        this.context = context;
        this.baseNodeViewFactory = baseNodeViewFactory;
        if (baseNodeViewFactory == null) {
            throw new IllegalArgumentException("You must assign a BaseNodeViewFactory!");
        }
    }

    public View getView() {
        if (rootView == null) {
            this.rootView = buildRootView();
        }

        return rootView;
    }

    @NonNull
    private RecyclerView buildRootView() {
        RecyclerView recyclerView = new RecyclerView(context);
        /**
         * disable multi touch event to prevent terrible data set error when calculate list.
         */
        recyclerView.setMotionEventSplittingEnabled(false);

        recyclerView.setItemAnimator(itemAnimator != null ? itemAnimator : new TreeItemAnimator());
        SimpleItemAnimator itemAnimator = (SimpleItemAnimator) recyclerView.getItemAnimator();
        itemAnimator.setSupportsChangeAnimations(false);

        recyclerView.setLayoutManager(new LinearLayoutManager(context));
        adapter = new TreeViewAdapter(context, root, baseNodeViewFactory);
        adapter.setNoShowIconLevel(noShowIconLevel);
        adapter.setTreeView(this);
        recyclerView.setAdapter(adapter);
        return recyclerView;
    }

    public void adapterNotify(){
        adapter.notifyDataSetChanged();
    }

    @Override
    public void expandAll() {
        if (root == null) {
            return;
        }
        TreeHelper.expandAll(root);

        refreshTreeView();
    }


    public void refreshTreeView() {
        if (rootView != null) {
            ((TreeViewAdapter) rootView.getAdapter()).refreshView();
        }
    }

    @Override
    public void expandNode(TreeNode treeNode) {
        adapter.expandNode(treeNode);
    }

    @Override
    public void expandLevel(int level) {
        TreeHelper.expandLevel(root, level);

        refreshTreeView();
    }

    @Override
    public void collapseAll() {
        if (root == null) {
            return;
        }
        TreeHelper.collapseAll(root);

        refreshTreeView();
    }

    @Override
    public void collapseNode(TreeNode treeNode) {
        adapter.collapseNode(treeNode);
    }

    @Override
    public void collapseLevel(int level) {
        TreeHelper.collapseLevel(root, level);

        refreshTreeView();
    }

    @Override
    public void toggleNode(TreeNode treeNode) {
        if (treeNode.isExpanded()) {
            collapseNode(treeNode);
        } else {
            expandNode(treeNode);
        }
    }

    @Override
    public void deleteNode(TreeNode node) {
        adapter.deleteNode(node);
    }

    @Override
    public void addNode(TreeNode parent, TreeNode treeNode) {
        parent.addChild(treeNode);

        refreshTreeView();
    }

    @Override
    public List<TreeNode> getAllNodes() {
        return TreeHelper.getAllNodes(root);
    }

    @Override
    public void selectNode(TreeNode treeNode) {
        if (treeNode != null) {
            Log.d("TreeView", " -=-=- selectNode: treeNode:" + treeNode);
            adapter.selectNode(true, treeNode);
        }
    }

    @Override
    public void deselectNode(TreeNode treeNode) {
        if (treeNode != null) {
            adapter.selectNode(false, treeNode);
        }
    }

    @Override
    public void selectAll() {
        TreeHelper.selectNodeAndChild(root, true);

        refreshTreeView();
    }

    @Override
    public void deselectAll() {
        TreeHelper.selectNodeAndChild(root, false);

        refreshTreeView();
    }

    @Override
    public List<TreeNode> getSelectedNodes() {
        return TreeHelper.getSelectedNodes(root);
    }

    public boolean isItemSelectable() {
        return itemSelectable;
    }

    public void setItemSelectable(boolean itemSelectable) {
        this.itemSelectable = itemSelectable;
    }
    private int[] noShowIconLevel;
    public TreeView setNoShowIconLevel(int[] noShowIconLevel) {
        this.noShowIconLevel = noShowIconLevel;
        return this;
    }
}

TreeItemAnimator树节点动画效果

public class TreeItemAnimator extends DefaultItemAnimator {
    @Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
        super.animateAdd(holder);
        ViewCompat.setAlpha(holder.itemView, 1);
        return true;
    }
}

TreeHelper负责节点管理

比如展开所有树型节点、选中某个父及其下子节点等。

public class TreeHelper {

    public static void expandAll(TreeNode node) {
        if (node == null) {
            return;
        }
        expandNode(node, true);
    }

    /**
     * Expand node and calculate the visible addition nodes.
     *
     * @param treeNode     target node to expand
     * @param includeChild should expand child
     * @return the visible addition nodes
     */
    public static List<TreeNode> expandNode(TreeNode treeNode, boolean includeChild) {
        List<TreeNode> expandChildren = new ArrayList<>();

        if (treeNode == null) {
            return expandChildren;
        }

        treeNode.setExpanded(true);

        if (!treeNode.hasChild()) {
            return expandChildren;
        }

        for (TreeNode child : treeNode.getChildren()) {
            expandChildren.add(child);

            if (includeChild || child.isExpanded()) {
                expandChildren.addAll(expandNode(child, includeChild));
            }
        }

        return expandChildren;
    }

    /**
     * Expand the same deep(level) nodes.
     *
     * @param root  the tree root
     * @param level the level to expand
     * @return
     */
    public static void expandLevel(TreeNode root, int level) {
        if (root == null) {
            return;
        }

        for (TreeNode child : root.getChildren()) {
            if (child.getLevel() == level) {
                expandNode(child, false);
            } else {
                expandLevel(child, level);
            }

        }
    }

    public static void collapseAll(TreeNode node) {
        if (node == null) {
            return;
        }
        for (TreeNode child : node.getChildren()) {
            performCollapseNode(child, true);
        }
    }

    /**
     * Collapse node and calculate the visible removed nodes.
     *
     * @param node         target node to collapse
     * @param includeChild should collapse child
     * @return the visible addition nodes before remove
     */
    public static List<TreeNode> collapseNode(TreeNode node, boolean includeChild) {
        List<TreeNode> treeNodes = performCollapseNode(node, includeChild);
        node.setExpanded(false);
        return treeNodes;
    }

    private static List<TreeNode> performCollapseNode(TreeNode node, boolean includeChild) {
        List<TreeNode> collapseChildren = new ArrayList<>();

        if (node == null) {
            return collapseChildren;
        }
        if (includeChild) {
            node.setExpanded(false);
        }
        for (TreeNode child : node.getChildren()) {
            collapseChildren.add(child);

            if (child.isExpanded()) {
                collapseChildren.addAll(performCollapseNode(child, includeChild));
            } else if (includeChild) {
                performCollapseNodeInner(child);
            }
        }

        return collapseChildren;
    }

    /**
     * Collapse all children node recursive
     *
     * @param node target node to collapse
     */
    private static void performCollapseNodeInner(TreeNode node) {
        if (node == null) {
            return;
        }
        node.setExpanded(false);
        for (TreeNode child : node.getChildren()) {
            performCollapseNodeInner(child);
        }
    }

    public static void collapseLevel(TreeNode root, int level) {
        if (root == null) {
            return;
        }
        for (TreeNode child : root.getChildren()) {
            if (child.getLevel() == level) {
                collapseNode(child, false);
            } else {
                collapseLevel(child, level);
            }
        }
    }

    public static List<TreeNode> getAllNodes(TreeNode root) {
        List<TreeNode> allNodes = new ArrayList<>();

        fillNodeList(allNodes, root);
        allNodes.remove(root);

        return allNodes;
    }

    private static void fillNodeList(List<TreeNode> treeNodes, TreeNode treeNode) {
        treeNodes.add(treeNode);

        if (treeNode.hasChild()) {
            for (TreeNode child : treeNode.getChildren()) {
                fillNodeList(treeNodes, child);
            }
        }
    }

    /**
     * Select the node and node's children,return the visible nodes
     *
     * @param treeNode
     * @param select
     * @return
     */
    public static List<TreeNode> selectNodeAndChild(TreeNode treeNode, boolean select) {
        List<TreeNode> expandChildren = new ArrayList<>();

        if (treeNode == null) {
            return expandChildren;
        }

        treeNode.setSelected(select);

        if (!treeNode.hasChild()) {
            return expandChildren;
        }

        if (treeNode.isExpanded()) {
            for (TreeNode child : treeNode.getChildren()) {
                expandChildren.add(child);

                if (child.isExpanded()) {
                    expandChildren.addAll(selectNodeAndChild(child, select));
                } else {
                    selectNodeInner(child, select);
                }
            }
        } else {
            selectNodeInner(treeNode, select);
        }
        return expandChildren;
    }

    private static void selectNodeInner(TreeNode treeNode, boolean select) {
        if (treeNode == null) {
            return;
        }
        treeNode.setSelected(select);
        if (treeNode.hasChild()) {
            for (TreeNode child : treeNode.getChildren()) {
                selectNodeInner(child, select);
            }
        }
    }

    /**
     * Select parent when all the brothers have been selected, otherwise deselect parent,
     * and check the grand parent recursive.
     *
     * @param treeNode
     * @param select
     * @return
     */
    public static List<TreeNode> selectParentIfNeedWhenNodeSelected(TreeNode treeNode, boolean select) {
        List<TreeNode> impactedParents = new ArrayList<>();
        if (treeNode == null) {
            return impactedParents;
        }

        //ensure that the node's level is bigger than 1(first level is 1)
        TreeNode parent = treeNode.getParent();
        if (parent == null || parent.getParent() == null) {
            return impactedParents;
        }

        List<TreeNode> brothers = parent.getChildren();
        int selectedBrotherCount = 0;
        for (TreeNode brother : brothers) {
            if (brother.isSelected()) selectedBrotherCount++;
        }

        if (select && selectedBrotherCount == brothers.size()) {
            parent.setSelected(true);
            impactedParents.add(parent);
            impactedParents.addAll(selectParentIfNeedWhenNodeSelected(parent, true));
        } else if (!select && selectedBrotherCount == brothers.size() - 1) {
            // only the condition that the size of selected's brothers
            // is one less than total count can trigger the deselect
            parent.setSelected(false);
            impactedParents.add(parent);
            impactedParents.addAll(selectParentIfNeedWhenNodeSelected(parent, false));
        }
        return impactedParents;
    }

    /**
     * Get the selected nodes under current node, include itself
     *
     * @param treeNode
     * @return
     */
    public static List<TreeNode> getSelectedNodes(TreeNode treeNode) {
        List<TreeNode> selectedNodes = new ArrayList<>();
        if (treeNode == null) {
            return selectedNodes;
        }

        if (treeNode.isSelected() && treeNode.getParent() != null) selectedNodes.add(treeNode);

        for (TreeNode child : treeNode.getChildren()) {
            selectedNodes.addAll(getSelectedNodes(child));
        }
        return selectedNodes;
    }

    /**
     * Return true when the node has one selected child(recurse all children) at least,
     * otherwise return false
     *
     * @param treeNode
     * @return
     */
    public static boolean hasOneSelectedNodeAtLeast(TreeNode treeNode) {
        if (treeNode == null || treeNode.getChildren().size() == 0) {
            return false;
        }
        List<TreeNode> children = treeNode.getChildren();
        for (TreeNode child : children) {
            if (child.isSelected() || hasOneSelectedNodeAtLeast(child)) {
                return true;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值