android - personalizado - Cómo tener un GridView que adapta su altura cuando se agregan elementos
gridview personalizado android (5)
Estoy tratando de mostrar una lista de cadenas en crecimiento dinámico con una casilla de verificación en un GridView, que se encuentra en TableLayout.
Puedo mostrar estas cadenas de "casillas de verificación" bien en una fila. Mi problema ocurre cuando dejo que el usuario agregue dinámicamente nuevas cadenas en GridView.
Creé un adaptador personalizado que recibe la lista de cadenas. Digamos que tenemos n cuerdas. El adaptador devuelve ''n + 1'' para el recuento de elementos; en getView, regresa:
- una Vista con LinearLayout, que tiene un CheckBox y un EditText para los primeros n elementos,
- un LinearLayout con un botón simple, con un título ''+'' para el elemento ''n + 1 °.
Hasta aquí todo bien. Cuando se hace clic en el botón ''+'', agrego una cadena vacía a la lista de cadenas y llamo notifyDataSetChanged en el adaptador.
El GridView se redibuja con un elemento más. PERO conserva su altura original y crea una barra de desplazamiento vertical. Me gustaría que GridView expanda su altura (es decir, ocupe más espacio en la pantalla y muestre todos los elementos).
Intenté cambiar la pantalla a LinearLayout vertical en lugar de a TableLayout, pero los resultados son los mismos.
Aquí está el diseño de mi pantalla:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<!-- other lines omitted -->
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/wine_rack_explanation"
android:layout_gravity="center_vertical" />
<GridView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/gvRack"
android:columnWidth="90dp"
android:numColumns="auto_fit" />
</LinearLayout>
<!-- other lines omitted -->
</LinearLayout>
</ScrollView>
El elemento checkbox + string del adaptador se define así:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<CheckBox android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cbCoordinate"
android:checked="true"
/>
<EditText android:id="@+id/txtCoordinate"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
El elemento del botón ''+'' se define así:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="@+id/btnAddBottle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add_bottle_caption" />
</LinearLayout>
Intenté llamar a invalidate o invalideViews en GridView después de agregar un elemento. También se llama invalidar en TableLayout y TableRow (en el diseño anterior de la pantalla). Sin éxito.
¿Alguna idea de por qué el GridView se niega a extender su altura?
(Tenga en cuenta que estoy completamente abierto a usar otro grupo de vista distinto al GridView)
Cuando se llama a onMeasure () para GridView, si heightMode es MeasureSpec.UNSPECIFIED, entonces la vista de grilla será tan alta como todos sus elementos contenidos (más algo de relleno).
Para garantizar que este sea el caso, puede hacer una vista personalizada rápida que extienda GridView e incluya la siguiente anulación:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
}
Esto es trabajo para mí:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background" >
<!-- MORE LAYOUTS IF YOU WANT -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:fillViewport="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- MORE LAYOUTS IF YOU WANT -->
<GridView
android:id="@+id/gridview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="5dp"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="10dp" >
</GridView>
<!-- MORE LAYOUTS IF YOU WANT -->
</RelativeLayout>
</ScrollView>
</RelativeLayout>
La solución de Graham no funcionó para mí. Sin embargo, este (con un poco más de pirateo) lo hizo: https://.com/a/8483078/479478
Lo he hecho de esta manera:
Este código establecerá la altura de GridView
según el número de Niño .
Nota: Donde 5
es el número de columnas.
private void setDynamicHeight(GridView gridView) {
ListAdapter gridViewAdapter = gridView.getAdapter();
if (gridViewAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int items = gridViewAdapter.getCount();
int rows = 0;
View listItem = gridViewAdapter.getView(0, null, gridView);
listItem.measure(0, 0);
totalHeight = listItem.getMeasuredHeight();
float x = 1;
if( items > 5 ){
x = items/5;
rows = (int) (x + 1);
totalHeight *= rows;
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight;
gridView.setLayoutParams(params);
}
Espero que esto te ayudará.
Usa este código
public class MyGridView extends GridView {
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}