rowspan gridlayout example columns cardview 3x3 android android-gridlayout

example - gridlayout android weight



La vista de texto con texto largo elimina otras vistas en GridLayout a pesar de que ellipsize=end (14)

Creo que deberías crear un diseño personalizado para tu propósito. No sé cómo hacer esto usando solo diseños / vistas por defecto y hacerlo funcionar para todos los casos.

Mi problema es muy similar a Cómo obtener un diseño donde un texto puede crecer y elipsis, pero no engullir los otros elementos en el diseño , pero lea a continuación por qué no puedo usar TableLayouts tal como se propone allí.

Estoy tratando de crear una fila de vista de lista que básicamente se ve así:

| TextView | Ver 1 | Ver 2 |

Todas las vistas contienen elementos de ancho variable. El TextView tiene ellipsize = "end" establecido. La Vista 1 debe alinearse a la izquierda de TextView, mientras que la Vista 2 debe alinearse a la derecha de la pantalla. Por lo tanto, normalmente, habría espacios en blanco entre la Vista 1 y la Vista 2. A medida que el texto en la Vista de texto crezca, la Vista de texto debería crecer, empujando la Vista 1 hacia la derecha hasta que no queden más espacios en blanco. Luego, ellipsize debería activarse, cortar el texto en TextView y agregar puntos suspensivos ("...") al final.

Entonces, el resultado debería verse más o menos así:

+----------------------------------------+ | short text [view1] [view2] | +----------------------------------------+ | long text with ell ... [view1] [view2] | +----------------------------------------+

He intentado:

  • TableLayouts, pero parecen hacer que el desplazamiento sea extremadamente lento en algunos dispositivos.
  • RelativeLayouts, pero tampoco tuve vistas superpuestas, o view1 o view2 desaparecieron por completo.
  • GridLayouts, pero TextView siempre crece hasta ocupar todo el ancho de la pantalla, lo que empuja a view1 y view2 fuera de la pantalla.

Este es el GridLayout que probé:

<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_gravity="left|fill_horizontal" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:layout_gravity="left" android:text="(view1)" /> <TextView android:layout_gravity="right" android:text="(view2)" /> </GridLayout>

La Vista 1 y la Vista 2 no son realmente TextViews, solo las utilicé en el ejemplo para simplificar las cosas.

¿Hay alguna forma de lograr esto sin usar TableLayouts?

EDITAR: Según lo solicitado, aquí está mi intento de resolver esto con un RelativeLayout. TextView ocupa todo el ancho de la pantalla en este caso, por lo que ni view1 ni view2 son visibles.

<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/rl0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:id="@+id/rl1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/rl0" android:layout_marginLeft="10dp" android:text="(view1)" /> <TextView android:id="@+id/rl2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/rl1" android:layout_alignParentRight="true" android:layout_marginLeft="10dp" android:text="(view2)" /> </RelativeLayout>


Creo que hay un pequeño problema en el diseño que podría resolverse, anclando la vista3 a la derecha y comenzando desde allí para obligar a la vista a tener un área delimitada (de ahí que se pueda establecer correctamente la elipse):

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/rl3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="(view2)" /> <TextView android:id="@+id/rl2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/rl3" android:text="(view1)" /> <TextView android:id="@+id/rl1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:singleLine="true" android:layout_alignParentLeft="true" android:layout_toLeftOf="@id/rl2" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> </RelativeLayout>

Espero que esto ayude...

¡Saludos!


El truco que funcionó para mí fue utilizar maxWidth para restringir el ancho de la primera vista. Necesitas hacerlo con Java, aquí está la lógica básica:

firstView.setMaxWidth(parentView.getWidth() - view2.getWidth() - view1.getWidth() - padding * 2);

No es bonita, pero funciona.


En primer lugar, debe diseñar [ver 2] para el derecho primario;

De nuevo, ¡usted hace referencia a la referencia a los dos últimos diseños!

<Relativelayout android:layout_width="match_parent" android:layout_height="wrap_content" <TextView android:id="@+id/view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toLeft="@id/view2" android:gravity="left"> <TextView android:id="@+id/shortORlongtTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/view1" android:ellipsize="end" android:maxLines="1" android:textSize="18dp"/> <TextView android:id="@+id/view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" /> </RelativeLayout>


Encuentro mi solución para el caso número 2 (el que tiene un texto largo):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:weightSum="3" > <TextView android:id="@+id/rl0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:id="@+id/rl1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_weight="1" android:text="(view1)" /> <TextView android:id="@+id/rl2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_weight="1" android:text="(view2)" /> </LinearLayout>

El verdadero problema es el primer caso, y no probé muchas cosas para esto. Espero que ayude (¡y si tengo más tiempo libre, trataré de lograr el primero!).


GridLayout es como las otras cosas en Android: defectuoso por diseño.

Necesitará un diseño personalizado, el siguiente ejemplo le permitirá diseñar cosas como:

[ label | short text | very long label | short text ] [ long label | very very very | label | very long text ] [ | long text | | ] import android.content.Context; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; public class TwoColumsGridLayout extends ViewGroup { private final List<List<View>> rows; private int rowCount = 0; private int firstColumWidth; private int secondColumWidth; private int thirdColumWidth; private int fourthColumnWidth; private final List<Integer> rowHeights = new ArrayList<>(); private final List<List<Integer>> cellHeights = new ArrayList<>(); private final List<Integer> firstCellsWidths = new ArrayList<>(4); private final List<Integer> thirdCellsWidths = new ArrayList<>(4); public TwoColumsGridLayout(Context context, int rowCount) { super(context); rows = new ArrayList<>(rowCount); } public void add(Context ctx, TextView l1, View t1, TextView l2, View t2) { final List<View> row = new ArrayList<>(4); row.add(l1); row.add(t1); row.add(l2); row.add(t2); rows.add(row); this.addView(l1); this.addView(t1); if (l2 != null) this.addView(l2); if (t2 != null) this.addView(t2); this.rowCount++; } public int getRowCount() { return rowCount; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int curLeft = 0; int curBottom; int curRight; int curTop = 0; int i = 0; for (List<View> row : rows) { final int rowHeight = this.rowHeights.get(i); final List<Integer> rowCellHeights = this.cellHeights.get(i); final View v0 = row.get(0); curLeft = 0; curRight = curLeft + this.firstColumWidth; if (v0 != null) { curBottom = curTop + rowCellHeights.get(0); // Right align v0.layout(curLeft + this.firstColumWidth - this.firstCellsWidths.get(i), curTop + 7, curRight, curBottom + 7); } // final View v1 = row.get(1); curLeft += this.firstColumWidth; curRight = curLeft + this.secondColumWidth; if (v1 != null) { curBottom = curTop + rowCellHeights.get(1); v1.layout(curLeft, curTop, curRight, curBottom); } // final View v2 = row.get(2); curLeft += this.secondColumWidth; curRight = curLeft + this.thirdColumWidth; if (v2 != null) { curBottom = curTop + rowCellHeights.get(2); // Right align v2.layout(curLeft + this.thirdColumWidth - this.thirdCellsWidths.get(i), curTop + 7, curRight, curBottom + 7); } // final View v3 = row.get(3); curLeft += this.thirdColumWidth; curRight = curLeft + this.fourthColumnWidth; if (v3 != null) { curBottom = curTop + rowCellHeights.get(3); v3.layout(curLeft, curTop, curRight, curBottom); } curTop += rowHeight; i++; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int parentWidth = MeasureSpec.getSize(widthMeasureSpec); // Compute first column width firstColumWidth = 0; for (List<View> row : rows) { final View v = row.get(0); if (v != null) { v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); measureChild(v, widthMeasureSpec, heightMeasureSpec); final int w = v.getMeasuredWidth(); if (firstColumWidth < w) { firstColumWidth = w; } } } // Compute third column width thirdColumWidth = 0; for (List<View> row : rows) { final View v = row.get(2); if (v != null) { v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); measureChild(v, widthMeasureSpec, heightMeasureSpec); final int w = v.getMeasuredWidth(); if (thirdColumWidth < w) { thirdColumWidth = w; } } } secondColumWidth = (parentWidth - firstColumWidth - thirdColumWidth) / 2; fourthColumnWidth = parentWidth - firstColumWidth - secondColumWidth - thirdColumWidth; // Clear this.rowHeights.clear(); this.cellHeights.clear(); this.firstCellsWidths.clear(); this.thirdCellsWidths.clear(); // Compute heights int height = 0; for (List<View> row : rows) { final ArrayList<Integer> rowCellHeights = new ArrayList<>(4); cellHeights.add(rowCellHeights); int rowHeight = 0; // First column final View v0 = row.get(0); if (v0 != null) { int h = v0.getMeasuredHeight(); this.firstCellsWidths.add(v0.getMeasuredWidth()); rowCellHeights.add(h); if (rowHeight < h) { rowHeight = h; } } else { this.firstCellsWidths.add(0); } // Second column final View v1 = row.get(1); if (v1 != null) { v1.setLayoutParams(new ViewGroup.LayoutParams(secondColumWidth, LayoutParams.WRAP_CONTENT)); measureChild(v1, widthMeasureSpec, heightMeasureSpec); int h = v1.getMeasuredHeight(); rowCellHeights.add(h); if (rowHeight < h) { rowHeight = h; } } // Third column final View v2 = row.get(2); if (v2 != null) { int h = v2.getMeasuredHeight(); this.thirdCellsWidths.add(v2.getMeasuredWidth()); rowCellHeights.add(h); if (rowHeight < h) { rowHeight = h; } } else { this.thirdCellsWidths.add(0); } // Fourth column final View v3 = row.get(3); if (v3 != null) { v3.setLayoutParams(new ViewGroup.LayoutParams(fourthColumnWidth, LayoutParams.WRAP_CONTENT)); measureChild(v3, widthMeasureSpec, heightMeasureSpec); int h = v3.getMeasuredHeight(); rowCellHeights.add(h); if (rowHeight < h) { rowHeight = h; } } height += rowHeight; this.rowHeights.add(rowHeight); } setMeasuredDimension(parentWidth, height); } }

Que te diviertas.


Intente usar el peso del diseño

<TableRow android:id="@+id/tableRow3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignBottom="@+id/tableRow2" android:layout_alignParentBottom="true" android:gravity="center" android:weightSum="10" android:background="@android:color/black" > <TextView android:id="@+id/txtInningsTotal" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" android:gravity="center" android:text="0" android:textColor="@android:color/white" /> <TextView android:id="@+id/txtTeamOneTotal" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2.5" android:gravity="center" android:text="0" android:textColor="@android:color/white" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="0.2" /> <TextView android:id="@+id/txtTeamTwoTotal" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2.5" android:gravity="center" android:text="0" android:textColor="@android:color/white" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="0.2" /> <TextView android:id="@+id/txtGrandTotal" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center" android:text="0" android:textColor="@android:color/white" /> </TableRow>

Aquí he tomado la fila de la tabla en la que hay una distribución del peso total que es de 10 significa que es 100% ancho de su elemento primario. y en todas sus vistas secundarias he establecido el ancho en 0Dp y dado un peso de 1 o 2. De modo que tomará hasta ese porcentaje del total de 10. Por lo tanto, el diseño se ajustará en consecuencia en la pantalla y también no habrá problemas de superposición. .

Si te he entendido correctamente, esta es la respuesta que querías.

¡Espero eso ayude!


Parece que encontré una posible solución para evitar que TextView en GridLayout crezca sin límites y se eliminen otras vistas. No estoy seguro si esto ha sido documentado anteriormente.

Debe usar fill layout_gravity y establecer un layout_width o ancho arbitrario en el largo TextView que necesita elipsis.

android:layout_gravity="fill" android:layout_width="1dp"

Funciona tanto para GridLayout como para android.support.v7.widget.GridLayout


Prueba esto

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:baselineAligned="false" android:orientation="horizontal"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:text="(view1)"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="(view2)"/> </LinearLayout> </LinearLayout>

Actualmente, todas las vistas están centradas. Puede cambiar android:gravity propiedad de android:gravity para satisfacer sus necesidades. Por ejemplo, es posible que desee alinear view1 derecha y view2 izquierda, en cuyo caso los dos últimos LinearLayout verían de forma similar (con margen de 5dp a la derecha e izquierda, respectivamente):

<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center|right"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:layout_marginRight="5dp" android:text="(view1)"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center|left"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:layout_marginLeft="5dp" android:text="(view2)"/> </LinearLayout>


Si el diseño de texto desplaza las vistas de la derecha, también podría usar un ListView en lugar de un GridView.

Solo necesita hacer que la base del diseño de elemento de la lista sea RelativeLayout, y establecer reglas como esta:

  1. Puede establecer las dos vistas a la derecha para alinear ParentRight (usando android: layout_alignParentLeft = "true"), pero asegúrese de que la primera vista permanezca a la izquierda del segundo, de modo que se empujará hacia la izquierda a medida que se extienden las vistas.

  2. Puede hacer que TextView a la izquierda se alinee a la izquierda, pero quédese a la izquierda de la primera vista (usando android: layout_toLeftOf = "@ + id / viewId") para que no se superponga con las vistas.


Soy un gran fanático de LinearLayouts, así que aquí está mi sugerencia de usarlos:

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_weight="1" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="(view1)" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="(view2)" /> </LinearLayout>


TableLayout dará el comportamiento esperado. Puede causar problemas de rendimiento como mención del autor de la pregunta, pero funciona muy bien con un diseño simple. Si la fila es repetible y desplazable, considere usar gridview en su lugar

<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="1" android:shrinkColumns="0" > <TableRow> <TextView/> <View1/> <View2/> </TableRow> </TableLayout>


Tuve el mismo problema con el diseño de la cuadrícula. lo que hice se le dio un ancho fijo para la vista de texto y también se le layout_columnWeight propiedad layout_columnWeight para cada vista de texto, luego se solucionó el problema, espero que ayude ...

<TextView android:id="@+id/txtName" style="@style/MyDetailTitle" android:layout_width="@dimen/detail_length" android:layout_height="wrap_content" android:text="@string/app_name" app:layout_column="3" app:layout_columnWeight="1" app:layout_gravity="start" app:layout_row="1" />


Sugeriré que juegues con la propiedad layout_weight de tu widget

Ejemplo:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:weightSum="10"> <LinearLayout android:id="@+id/ll_twoViewContainer" android:layout_weight="8" android:layout_width="0dp" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/rl0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_weight="1" android:ellipsize="end" android:singleLine="true" android:text="Long text" /> <TextView android:id="@+id/rl1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_toRightOf="@id/rl0" android:layout_weight="1" android:minWidth="120dp" android:text="(view1)" /> </LinearLayout> <TextView android:id="@+id/rl2" android:layout_weight="2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_toRightOf="@id/rl1" android:layout_alignParentRight="true" android:layout_marginLeft="10dp" android:text="(view2)" /> </LinearLayout> </LinearLayout>

finalmente su diseño se verá como sigue:

+----------------------------------------+ | short text [view1] [view2] | +----------------------------------------+ | long text with ell ... [view1] [view2] | +----------------------------------------+