Android 树形结构(AndroidTreeView)github地址:https://github.com/bmelnychuk/AndroidTreeView
引入方式:implementation 'com.github.bmelnychuk:atv:1.2.+'
具体使用请移步github官网
跑了官网的例子,发现父节点勾选后子节点会全部选中,父节点取消勾选后子节点也会全部取消选中
但是在父节点勾选后子节点全部选中的情况下,点击一个子节点不勾选,这时父节点没有取消勾选,居于这种(类似于删除文件有一个没选即不能为全选)使用场景,修改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监听,同时也对子节点和父节点分别进行勾选与不勾选的判断处理,这样就避免了上文的情况的发生。
希望有需要的朋友可以帮到你们,如有不对之处,烦请留言指正谢谢!