¿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:
- A veces listView.getChildAt (int index) devuelve NULL (Android)
- ¿Cómo usar correctamente setZOrderMediaOverlay en Android?
- Android ExpandableListView - establece cierto grupo para no expandible
- Dibujo fuera de pantalla WebView a mapa de bits
- Android ListView en el widget onClick no funciona
_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"/>
- Cómo obtener la vista del grupo en la lista expandiblelist en android?
- Optimizaciones de Scrollview
- Arrastrar y soltar en android 3.x causa illegalStateException después de pequeño número en arrastra
- FilePicker desde android webview trabajando sólo una vez
- Diferencia entre View y ViewGroup en Android
- Android: aplica una transformación arbitraria a una vista
- ¿Cómo puedo obtener la altura del teclado del método de entrada actual sin mostrarlo?
- Diferencia entre OnTouchListener y OnClickListener
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; }
- Utilizar RxJava para encadenar la solicitud en un solo hilo
- Cambiar el estilo del menú emergente – no funciona