Android:如何修复意外取消选中树中父节点的复选框

时间:2016-04-30 10:49:51

标签: java android checkbox tree

我编写了类来表示树文件层次结构。主要任务 - 标记文件和文件夹的能力(使用复选框)。遇到过这样的问题:使用以下一系列操作消失父目录的复选标记:

0)转到根目录,检查文件(保留一个目录未选中)

1)转到未经检查的目录并检查任何文件(或更多)

2)返回更高级别并取消选中目录,其中执行了操作(1)

返回到更高级别,您将看到未检查父目录的复选标记(尽管根目录中至少有一个已检查的文件)。

很多天我都在寻找一个问题。也许有人会注意到错误。提前谢谢。

截图:

Bug

Normal state

班级:

public class FileTree {
    /* The name for pointer to the parent node */
    public static final String PARENT_DIR = "..";

    private String mName;
    private boolean mIsLeaf;
    private boolean mIsChecked = false;
    private long mSize;
    /* Number of checked children */
    private int childrenCheckNum = 0;
    private FileTree mParent;
    private Map<String, FileTree> mChildren = new LinkedHashMap<String, FileTree>();

    public FileTree(String name, long size, int type)
    {
        this(name, size, type, null);
    }

    public FileTree(String name, long size, int type, FileTree parent)
    {
        mName = name;
        mIsLeaf = type == FileNode.Type.FILE;
        mParent = parent;
        mSize = size;
    }

    public void addChild(FileTree node)
    {
        if (!mChildren.containsKey(node.getName())) {
            mChildren.put(node.getName(), node);
            mSize += node.size();
            if (mParent != null) {
                mParent.onChildAdd(node.size());
            }
        }
    }

    /*
     * Sending new child size up the tree.
     */

    private void onChildAdd(long size)
    {
        mSize += size;
        if (mParent != null) {
            mParent.onChildAdd(size);
        }
    }

    public boolean findChild(String name)
    {
        if (mChildren.containsKey(name)) {
            return true;
        }

        return false;
    }

    ...

    public boolean isChecked()
    {
        return mIsChecked;
    }

    public void setCheck(boolean check)
    {
        mIsChecked = check;

        /* Sending check change event up the parent */
        if (mParent != null && mParent.isChecked() != check) {
            mParent.onChildCheckChange(check);
        }

        /* Sending check change event down the tree */
        if (getChildrenCount() != 0) {
            childrenCheckNum = check ? getChildrenCount() : 0;

            for (FileTree node : mChildren.values()) {
                if (node.isChecked() != check) {
                    node.setCheck(check);
                }
            }
        }
    }

    /*
     * Sending check change events up the tree.
     */

    private void onChildCheckChange(boolean check)
    {
        if (check) {
            ++childrenCheckNum;
            mIsChecked = true;
        } else {
            if (childrenCheckNum > 0) {
                --childrenCheckNum;
            }

            /* Uncheck parent only if don't left selected children nodes */
            if (childrenCheckNum == 0) {
                mIsChecked = false;
            }
        }

        /* Sending check change event up the parent */
        if (mParent != null && mParent.isChecked() != check) {
            mParent.onChildCheckChange(check);
        }
    }
    ...
}

1 个答案:

答案 0 :(得分:0)

我简化了onChildCheckChanged,现在它正常运行

private synchronized void onChildCheckChange()
    {
        if (getChildrenCount() == 0) {
            return;
        }

        long childrenCheckNum = 0;
        for (FileTree child : children.values()) {
            if (child.isChecked) {
                ++childrenCheckNum;
            }
        }

        /* Uncheck parent only if don't left selected children nodes */
        isChecked = childrenCheckNum > 0;

        /* Sending check change event up the parent */
        if (parent != null && parent.isChecked() != isChecked) {
            parent.onChildCheckChange();
        }
    }