¿Cómo uso ResourceCursorTreeAdapter con vistas de grupo expandidas y contraídas en Android?

¿Cómo uso el ResourceCursorTreeAdapter con el constructor siguiente?

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

Estoy tratando de usar una de la siguiente manera:

 _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; } ... 

Si el nodo del grupo está expandido, quiero que el nodo del grupo incluya el encabezado de una tabla que cada fila se mantenga en un nodo secundario. timing_group_view_expanded.xml y timing_group_view_collapsed.xml se muestran en la parte inferior de esta pregunta. Por alguna razón, nunca se utiliza la función group_view_expanded si los nodos de grupo se expanden o se contraen. ¿Estoy usando esto mal? ¿Alguien más ha podido obtener ResourceCursorTreeAdapter con este constructor para trabajar?

timing_group_view_expanded.xml es el siguiente:

 <?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 se parece a lo siguiente:

 <?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"/> 

El problema es que ResourceCursorTreeAdapter sólo crea los diseños correctos en la creación de una vista. Por lo tanto, si un grupo se contrae o se amplía, newGroupView() no se vuelve a llamar y, por lo tanto, los diferentes diseños de grupo pasados ​​al constructor no se utilizan como se esperaba.

El mismo problema existe con los diseños de los niños cuando se utilizan diferentes para el niño normal y el último. Sucede allí sin siquiera cambiar los datos! Después de re-expandir un grupo, el primero tenía el diseño de pie de página y viceversa. Totalmente aleatorio y no basado en la posición en la lista.

Como Aleksander O demostró en su ejemplo, se puede arreglar esto llamando siempre newGroupView() en el método getGroupView (y getChildView respectivamente si se usan diferentes diseños para eso).

Para evitar siempre crear nuevas vistas, he intentado un enfoque diferente que funciona para mi caso:

  • Agregue diferentes identificadores al elemento raíz de los diseños utilizados para las vistas de grupo / secundario
  • Almacene esos view-ids como miembros int de mi Adaptador:

     // 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(); 
  • Implementación de getGroupView (y análogo con 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; } 

Esta es mi solución temporal para 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; } } 

Fácil solución con buen reciclaje.

 @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; } 
  • Vista vacía en el adaptador de lista expandible
  • Diferente ancho de diseño dentro de RecyclerView y LinearLayout normal
  • imagen de ajuste de androide en imagen
  • Barra de búsqueda personalizada con los bordes cortados
  • HasStableIds () en ListView expandible?
  • Problema para agregar vista dinámicamente en Linearlayout
  • Recepción de la barra de estado oculta / entrada de un evento de actividad de pantalla completa en un servicio
  • Ocultar barra de desplazamiento de HorizontalScrollView
  • Analógico de android: filterTouchesWhenObscured para el nivel de API inferior a 9
  • ¿Cuál es la forma correcta de comunicarse desde una Vista personalizada a la Actividad en la que reside?
  • WebViewClient no se puede resolver con un tipo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.