如何将“虚拟”/“阴影”组添加到SimpleCursorTreeAdapter?

问题描述:

我有一个SimpleCursorTreeAdapter的问题,我在我的项目中进行了分类。它目前通过ContentProvider与SQLite-DB进行通信。现在,我遇到了问题,我想插入某种不存在于后端ContentProvider/DB中的“影子”或“虚拟”组。如何将“虚拟”/“阴影”组添加到SimpleCursorTreeAdapter?

我可以想象,这是可能的两种方式 - 我只是不能解决细节问题。我们可以找到实际的方法在内部绘制并列出SimpleCursorTreeAdapter的组,或者我们实现一个自定义的Cursor,其行为与SQliteCursor相似,不同之处在于它返回ColumnCount + 1并在查询时为该“虚拟”组附加一个“虚拟”元素...

有没有人已经做过这样的事情,或者可能有一个想法如何解决这个不太肮脏的黑客行为?

+0

你想在哪里插入“影子”组?它应该如何表现(它总是可见的,在某些条件下隐藏)? – Luksprog 2013-03-01 13:06:05

+0

它会显示和表现为一个常规组。在getChildrenCursor中,我会返回一个在不同的ContentProvider(或同一个ContentProvider的不同表)上运行的游标,从而提供对无法显示的数据的访问。 – 2013-03-01 13:36:12

+0

我明白,但还有另外一个问题:你想在哪里放置这个额外的小组?在列表的开始或结束时,或在其两个元素之间的光标中间的某个位置? – Luksprog 2013-03-01 14:17:00

...或者我们实现查询时,其行为类似SQliteCursor, 只不过它返回的列数+ 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处的假行(但通过仔细计算,可以使用不同的位置)。

+0

嗨Luksprog,感谢您非常详尽的回复和代码!我目前正试图将其整合到我的项目中,并查看并了解实际发生的情况。感谢您的时间和精彩的工作!我将在运行后重新报告(或再次卡住)。我担心周末没有太多时间,但在下周一开始,我将能够报告回来!谢谢! – 2013-03-01 19:45:22