Me gustaría que los elementos de mi GridView
fueran cuadrados. Hay 2 columnas y el ancho de los elementos es fill_parent
(por ejemplo, ocupan tanto espacio horizontal como sea posible. Los elementos son vistas personalizadas.
¿Cómo hago para que la altura de los elementos sea igual a su ancho variable?
O si desea extender una Vista, simplemente haga algo realmente simple como:
public class SquareImageView extends ImageView { public SquareImageView(final Context context) { super(context); } public SquareImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } public SquareImageView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec); setMeasuredDimension(width, width); } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { super.onSizeChanged(w, w, oldw, oldh); } }
Vale la pena señalar que
super.onMeasure()
no es necesario.onMeasured
requisito es que debes llamarsetMeasuredDimension
.fuente
super.onMeasure()
, no se dibujará un ImageView colocado dentro. Entonces parece que se requiere como primera línea delonMeasure
método.No estoy seguro de que esto sea posible con los widgets actuales. Su mejor opción podría ser poner su vista personalizada en un "SquareView" personalizado. Esta vista solo podría contener 1 vista secundaria y forzar la altura para que sea igual al ancho cuando se llama a su método onLayout.
Nunca intenté hacer algo así, pero creo que no debería ser demasiado difícil. Una solución alternativa (y tal vez un poco más fácil) podría ser subclasificar el diseño raíz de su vista personalizada (por ejemplo, si es un LinearLayout, haga un SquareLinearLayout) y usarlo como un contenedor en su lugar.
editar: Aquí hay una implementación básica que parece funcionar para mí:
package com.mantano.widget; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class SquareView extends ViewGroup { public SquareView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int l, int u, int r, int d) { getChildAt(0).layout(0, 0, r-l, d-u); // Layout with max size } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { View child = getChildAt(0); child.measure(widthMeasureSpec, widthMeasureSpec); int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec); child.measure(width, width); // 2nd pass with the correct size setMeasuredDimension(width, width); } }
Está diseñado para tener un hijo único, pero ignoré todas las comprobaciones por simplicidad. La idea básica es medir al niño con los parámetros de ancho / alto establecidos por GridView (en mi caso, usa numColumns = 4 para calcular el ancho), y luego hacer una segunda pasada con las dimensiones finales, con alto = ancho. .. El diseño es simplemente un diseño simple, que coloca al niño único en (0, 0) con las dimensiones deseadas (derecha-izquierda, abajo-arriba).
Y aquí está el XML utilizado para los elementos de GridView:
<?xml version="1.0" encoding="utf-8"?> <com.mantano.widget.SquareView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/item" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:gravity="center"> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello world" /> </LinearLayout> </com.mantano.widget.SquareView>
Usé un LinearLayout dentro de SquareView para que administre todas las posibilidades de gravedad, márgenes, etc.
No estoy seguro de qué tan bien (o mal) reaccionaría este widget a los cambios de orientación y dimensión, pero parece funcionar correctamente.
fuente
Termina siendo bastante fácil conseguir que el elemento de la cuadrícula quede cuadrado.
En su método "GetView" de su adaptador de red, simplemente haga:
@Override public View getView(int position, View convertView, ViewGroup parent) { GridView grid = (GridView)parent; int size = grid.getRequestedColumnWidth(); TextView text = new TextView(getContext()); text.setLayoutParams(new GridView.LayoutParams(size, size)); // Whatever else you need to set on your view return text; }
fuente
getRequestedColumnWidth
congetColumnWidth
y trabajó para mí ... gracias!No sé si es la mejor manera, pero lo logro haciendo que mi vista personalizada anule onSizeChanged de esa manera:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (getLayoutParams() != null && w != h) { getLayoutParams().height = w; setLayoutParams(getLayoutParams()); } }
¡Utilizo esta vista personalizada dentro de LinearLayout y GridView y en ambos se muestra un cuadrado!
fuente
¡Esto funcionó para mí!
Si eres como yo y no puedes usar getRequestedColumnWidth () porque tu minSdk es menor que 16, sugiero esta opción.
en tu fragmento:
DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); int size = dm.widthPixels / nbColumns; CustomAdapter adapter = new CustomAdapter(list, size, getActivity());
en su adaptador (en getView (int position, View convertView, ViewGroup parent))
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
fragment.xml:
<GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="match_parent" android:horizontalSpacing="3dp" android:verticalSpacing="3dp" android:numColumns="4" android:stretchMode="columnWidth" />
custom_item.xml: (por ejemplo)
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" />
¡Espero que ayude a alguien!
fuente
si establece un número estático de columnas en el xml, puede tomar el ancho de la vista y dividirlo por el número de columnas.
si está utilizando
auto_fit
, será un poco complicado obtener el recuento de columnas (no hay un método getColumnCount ()), por cierto, esta pregunta debería ayudarlo de alguna manera.este es el código que estoy usando en el
getView(...)
método del adaptador con un número fijo de columnas:item_side = mFragment.holder.grid.getWidth() / N_COL; v.getLayoutParams().height = item_side; v.getLayoutParams().width = item_side;
fuente
Tratar
<GridView ... android:stretchMode="columnWidth" />
También puedes jugar con otros modos
fuente
Esto es lo que estoy haciendo para mostrar celdas cuadradas en un GridView. No estoy seguro de si desea celdas cuadradas o algo más.
GridView grid = new GridView( this ); grid.setColumnWidth( UIScheme.cellSize ); grid.setVerticalSpacing( UIScheme.gap ); grid.setStretchMode( GridView.STRETCH_COLUMN_WIDTH ); grid.setNumColumns( GridView.AUTO_FIT );
Y luego la vista que estoy creando para cada celda tengo que hacer lo siguiente:
cell.setLayoutParams( new GridView.LayoutParams(iconSize, iconSize) );
fuente
Basado en la respuesta de SteveBorkman , que es API 16+:
@Override public View getView(int position, View convertView, ViewGroup parent) { GridView grid = (GridView)parent; int size = grid.getColumnWidth(); if (convertView == null){ convertView = LayoutInflater.from(context).inflate(R.layout.your_item, null); convertView.setLayoutParams(new GridView.LayoutParams(size, size)); } //Modify your convertView here return convertView; }
fuente
En la línea de la respuesta de @ Gregory, tuve que envolver mi imagen en un LinearLayout para evitar que GridView manipulara sus dimensiones desde el cuadrado. Tenga en cuenta que el LinearLayout externo debe configurarse para tener la dimensión de la imagen, y el ancho de la columna GridView debe ser el ancho de la imagen MÁS cualquier margen. Por ejemplo:
<!-- LinearLayout wrapper necessary to wrap image button in order to keep square; otherwise, the grid view distorts it into rectangle. also, margin top and right allows the indicator overlay to extend top and right. NB: grid width is set in filter_icon_page.xml, and must correspond to size + margin --> <LinearLayout android:id="@+id/sport_icon_lay" android:layout_width="60dp" android:layout_height="60dp" android:orientation="vertical" android:layout_marginRight="6dp" android:layout_marginTop="6dp" > <ImageButton android:id="@+id/sport_icon" android:layout_width="60dp" android:layout_height="60dp" android:maxHeight="60dp" android:maxWidth="60dp" android:scaleType="fitCenter" /> </LinearLayout>
y el GridView como:
<GridView android:id="@+id/grid" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fillViewport="true" android:columnWidth="66dp" android:numColumns="auto_fit" android:verticalSpacing="25dp" android:horizontalSpacing="24dp" android:stretchMode="spacingWidth" />
fuente
En tu actividad
DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); valX = displaymetrics.widthPixels/columns_number;
en el CustomAdapter de GridView
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, YourActivity.valX));
fuente