【问题标题】:How to add a "Virtual"/"Shadow" Group to SimpleCursorTreeAdapter?如何将“虚拟”/“阴影”组添加到 SimpleCursorTreeAdapter?
【发布时间】:2013-02-15 20:58:35
【问题描述】:

我有一个关于我在项目中子类化的 SimpleCursorTreeAdapter 的问题。它目前通过 ContentProvider 与 SQLite-DB 通信。现在,我有一个问题,我想插入后端 ContentProvider/DB 中不存在的某种“影子”或“虚拟”组。

我可以想象这可以通过两种方式实现——我只是无法弄清楚细节。我们要么在内部找到绘制和列出 SimpleCursorTreeAdapter 组的实际方法,要么实现一个行为类似于 SQliteCursor 的自定义 Cursor,除了它返回 ColumnCount+1 并在查询时为该“虚拟”组附加一个“虚拟”元素...

有没有人已经做过这样的事情,或者可能知道如何解决这个不太脏的黑客问题?

【问题讨论】:

  • 你想在哪里插入“影子”组?它应该如何表现(它总是可见的,在某些条件下隐藏)?
  • 它会像普通组一样显示和表现。在 getChildrenCursor 中,我将返回一个在不同 ContentProvider(或同一 contentprovider 的不同表)上运行的游标,从而提供对否则无法显示的数据的访问。
  • 我明白了,但还有一个问题:你想把这个额外的组放在哪里?在列表的开头或结尾,或者游标的两个元素之间的中间某处?
  • 哦,我误解了你的问题,对不起。我想我会喜欢它在我的列表的开头,但如果有一个通用的解决方案,我认为这对将来偶然发现这个问题的人最有帮助。我认为开始或结束会帮助很多人!

标签: android listadapter inject


【解决方案1】:

... 或者我们实现一个行为类似于 SQliteCursor 的自定义光标, 除了它返回 ColumnCount+1 并附加一个“虚拟”元素 查询时为那个“虚拟”组...

或者你在适配器级别实现它,欺骗它认为所基于的Cursor 有一个额外的行。我写了一个例子(一个简单的场景),但它需要工作:

public class ExtraGroupAdapter extends SimpleCursorTreeAdapter {

    private Cursor mExtraChildCursor;       

    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        // if groupCursor.getPosition() returns -1 we have to provide the Cursor for our fake group
    }

    @Override
    public int getGroupCount() {
        // 1 more
        return super.getGroupCount() + 1;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        if (groupPosition == 0) {
            if (getCursor() == null) {
                throw new IllegalStateException(
                        "this should only be called when the cursor is valid");
            }
            View v;
            if (convertView == null) {
                v = newGroupView(mContext, getCursor(), isExpanded, parent);
            } else {
                v = convertView;
            }
            // if it's position 0 move the group Cursor to position -1 to
            // let the bindGroupView method that is deals with our fake row
            getCursor().moveToPosition(-1);
            bindGroupView(v, mContext, getCursor(), isExpanded);
            return v;
        } else {
            return super.getGroupView(groupPosition - 1, isExpanded,
                    convertView, parent);
        }
    }

    @Override
    protected void bindGroupView(View view, Context context, Cursor cursor,
            boolean isExpanded) {
        if (cursor.getPosition() == -1) {
            // bind our fake row, unfortunately this must be done manually
        } else {
            super.bindGroupView(view, context, cursor, isExpanded);
        }
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        if (groupPosition == 0) {
            // replicate what the CursorTreeAdapter does for our fake group
            // position 0
            if (getCursor() == null) {
                throw new IllegalStateException(
                        "this should only be called when the cursor is valid");
            }
            View v;
            getCursor().moveToPosition(-1);
            mExtraChildCursor.moveToPosition(childPosition);
            if (convertView == null) {
                v = newChildView(mContext, mExtraChildCursor, isLastChild,
                        parent);
            } else {
                v = convertView;
            }
            bindChildView(v, mContext, mExtraChildCursor, isLastChild);
            return v;
        } else {
            // use the default implementation but offset the Cursor's
            // current position
            return super.getChildView(groupPosition - 1, childPosition,
                    isLastChild, convertView, parent);
        }
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        if (groupPosition == 0) {
            // implement the trick
            if (mExtraChildCursor == null) {
                getCursor().moveToPosition(-1); // in the getChildrenCursor
                                                // a Cursor position of -1
                                                // means it is the fake row
                mExtraChildCursor = getChildrenCursor(getCursor());
                return 0;
            } else {
                return mExtraChildCursor.getCount();
            }
        }
        return super.getChildrenCount(groupPosition);
    }

    @Override
    public void setChildrenCursor(int groupPosition, Cursor childrenCursor) {
        if (groupPosition == 0) {
            // hold a reference to the extra Cursor
            mExtraChildCursor = childrenCursor;
            notifyDataSetChanged();
        } else {
            super.setChildrenCursor(groupPosition, childrenCursor);
        }
    }

}

我应该扩展CursorTreeAdapter,因为SimpleCursorTreeAdapter 是为简单场景设计的。我写的是放置在位置 0 的假行(但经过仔细计算,可以使用不同的位置)。

【讨论】:

  • 嗨 Luksprog,感谢您非常详尽的回复和代码!我目前正在尝试将其集成到我的项目中,并查看并了解那里实际发生的情况。非常感谢您的时间和出色的工作!我会在它运行后报告(或再次卡住)。我担心我周末没有太多时间,但在下周开始时,我将能够回来报告!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多