开发者

How do I use ResourceCursorTreeAdapter with expanded and collapsed group views in Android?

开发者 https://www.devze.com 2022-12-15 10:38 出处:网络
How do I use the ResourceCursorTreeAdapter with the following constructor? ResourceCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, int expandedGroupLayout, int childLayout

How do I use the ResourceCursorTreeAdapter with the following constructor?

ResourceCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, int expandedGroupLayout, int childLayout)

I'm trying to use a it as follows:

_resultsCursorTreeAdapter = new ResourceCursorTreeAdapter(_resultsList.getContext(), _dbAdapter.getAllGroups(), 
        R.layout.timing_group_view_collapsed, R.layout.timing_group_view_expanded, R.layout.timing_result_view) {

 @Override
 protected Cursor getChildrenCursor(Cursor groupCursor) {
  // Given the group, we return a cursor for all the children within that group 
  int groupId = groupCursor.getInt(0);
  Cursor childCursor = _dbAdapter.getContractionsForGroup(groupId);
  return childCursor;
 }

 @Override
 protected void bindGroupView(View groupView, Context context, Cursor cursor,
     boolean isExpanded) {

  TimingGroupView timingGroupItem =  null;
  if(groupView instanceof LinearLayout){
   Log.i("TimingGroupView", "Has Header");
   LinearLayout layout = (LinearLayout)groupView;

   timingGroupItem = (TimingGroupView) layout.getChildAt(0);
  } else{
   Log.i("TimingGroupView", "No Header");
   timingGroupItem = (TimingGroupView) groupView;
  } 
 ...

If the group node is expanded, I want the group node to include the header for a table which each row is held in a child node. timing_group_view_expanded.xml and timing_group_view_collapsed.xml are shown at the bottom of this question. For some reason, the group_view_expanded is never used whether the group nodes are expanded or collapsed. Am I using this wrong? Has anyone else been able to get ResourceCursorTreeAdapter with this constructor to work?

timing_group_view_expanded.xml is as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/timing_group_view"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android"
 android:background=开发者_开发问答"@color/header_timing_color">

 <com.contractiontracker.TimingGroupView
  android:id="@+id/timing_group_item" xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="wrap_content"
  android:layout_marginLeft="30px" android:padding="10dp"
  android:scrollbars="vertical" 
  android:fadingEdge="vertical" 
  android:background="@color/header_timing_color"
  android:textColor="@color/text_color"/>

 <com.contractiontracker.RowLayout android:id="@+id/timing_group_view"
  android:orientation="horizontal" android:layout_width="fill_parent"
  android:layout_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android"
  android:background="@color/header_color" android:textColor="@color/text_color">

  <TextView android:id="@+id/interval_header"
   android:layout_width="fill_parent" android:layout_height="wrap_content"
   android:text="Interval" android:layout_weight="1"
   android:layout_gravity="left|bottom" android:gravity="center" 
   android:textColor="@color/text_color">
  </TextView>
  <TextView android:id="@+id/duration_header"
   android:layout_width="fill_parent" android:layout_height="wrap_content"
   android:text="Duration" android:layout_weight="1"
   android:layout_gravity="center_horizontal|bottom" android:gravity="center"
   android:textColor="@color/text_color"
   >
  </TextView>
  <TextView android:id="@+id/intensity_header"
   android:layout_width="fill_parent" android:layout_height="wrap_content"
   android:text="Intensity" android:layout_weight="1"
   android:layout_gravity="right|bottom" android:gravity="center"
   android:textColor="@color/text_color"
   >
  </TextView>
</com.contractiontracker.RowLayout>
</LinearLayout>

timing_group_view_collapsed.xml looks like the following:

<?xml version="1.0" encoding="utf-8"?>
<com.contractiontracker.TimingGroupView 
  android:id="@+id/timing_group_item"
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:layout_marginLeft="50px" 
 android:padding="10dp"
 android:scrollbars="vertical"
 android:textColor="@color/text_color"
 android:fadingEdge="vertical"/>


The problem is that ResourceCursorTreeAdapter only creates the correct layouts on creation of a view. So if a group gets collapsed or expanded the newGroupView() is not called again and therefore the different group layouts passed into the constructor are not used as expected.

Same problem exists with the child layouts when using different ones for normal and last child. It happens there without even changing the data! After re-expanding a group the first one had the footer layout and vice-versa. Totally random and not based on position in the list.

As Aleksander O showed in his example, one can fix this by always call newGroupView() in the getGroupView method (and the getChildView respectively if different layouts are used for that).

To avoid always create new views, I tried a different approach that works for my case:

  • Add different ids to the root element of the layouts used for group/child views
  • Store those view-ids as int members of my Adapter:

    // Get the view ids for comparison
    View view = newGroupView(mContext, null, false, null);
    mCollapsedGroupLayoutViewId = view.getId();
    view = newGroupView(mContext, null, true, null);
    mExpandedGroupLayoutViewId = view.getId();
    
    view = newChildView(mContext, null, false, null);
    mChildLayoutViewId = view.getId();
    view = newChildView(mContext, null, true, null);
    mLastChildLayoutViewId = view.getId();
    
  • Implementation of getGroupView (and analog with getChildView):

    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            Cursor cursor = getGroup(groupPosition);
            if (cursor == null) {
                throw new IllegalStateException("this should only be called when the cursor is valid");
            }
    
            View v;
            if (convertView == null 
              || (isExpanded && convertView.getId() == mCollapsedGroupLayoutViewId) 
              || (!isExpanded && convertView.getId() == mExpandedGroupLayoutViewId)) {
                v = newGroupView(mContext, cursor, isExpanded, parent);
            }
            else {
                v = convertView;
            }
            bindGroupView(v, mContext, cursor, isExpanded);
            return v;
    }
    


Here's my temporary solution for SimpleExpandableListAdapter:

public class LocalAdapter extends SimpleExpandableListAdapter {
    private List<? extends Map<String, ?>> mGroupData;
    private String[] mGroupFrom;
    private int[] mGroupTo;

    private List<? extends List<? extends Map<String, ?>>> mChildData;

    private LayoutInflater mInflater;

    public LocalAdapter(Context context,
            List<? extends Map<String, ?>> groupData, int groupLayout,
            String[] groupFrom, int[] groupTo,
            List<? extends List<? extends Map<String, ?>>> childData,
            int childLayout, String[] childFrom, int[] childTo) {
        this(context, groupData, groupLayout, groupLayout, groupFrom, groupTo, childData,
                childLayout, childLayout, childFrom, childTo);
    }

    public LocalAdapter(Context context,
            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
            List<? extends List<? extends Map<String, ?>>> childData,
            int childLayout, String[] childFrom, int[] childTo) {
        this(context, groupData, expandedGroupLayout, collapsedGroupLayout,
                groupFrom, groupTo, childData, childLayout, childLayout,
                childFrom, childTo);
    }

    public LocalAdapter(Context context,
            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
            List<? extends List<? extends Map<String, ?>>> childData,
            int childLayout, int lastChildLayout, String[] childFrom,
            int[] childTo) {

        super(context, groupData, expandedGroupLayout,
                collapsedGroupLayout, groupFrom, groupTo, childData,
                childLayout, lastChildLayout, childFrom, childTo);

        mGroupData = groupData;
        mGroupFrom = groupFrom;
        mGroupTo = groupTo;
        mChildData = childData;
        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }        

    private void bindView(View view, Map<String, ?> data, String[] from, int[] to) {
        int len = to.length;

        for (int i = 0; i < len; i++) {
            TextView v = (TextView)view.findViewById(to[i]);
            if (v != null) {
                v.setText((String)data.get(from[i]));
            }
        }
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
            ViewGroup parent) {
        View v = newGroupView(isExpanded, parent);
        bindView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);
        return v;
    }
}


Easy solution with good recycling.

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    Cursor cursor = getGroup(groupPosition);
    if (cursor == null) {
        throw new IllegalStateException("this should only be called when the cursor is valid");
    }

    View view;
    if (convertView == null || convertView.getTag() != isExpanded) {
        view = newGroupView(mActivity, cursor, isExpanded, parent);
        view.setTag(isExpanded);
    } else {
        view = convertView;
    }
    bindGroupView(view, mActivity, cursor, isExpanded);
    return view;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消