ImageView ser un cuadrado con ancho dynamic?

Tengo un GridView con ImageViews adentro. Tengo 3 de ellos por cada fila. Puedo establecer correctamente el ancho con WRAP_CONTENT y scaleType = CENTER_CROP, pero no sé cómo configurar el tamaño de ImageView para que sea un cuadrado. Esto es lo que hice hasta ahora, parece estar bien, excepto la altura, que es “estática”:

imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setLayoutParams(new GridView.LayoutParams(GridView.LayoutParams.WRAP_CONTENT, 300)); 

Lo estoy haciendo dentro de un adaptador.

La mejor opción es subclasificar ImageView usted mismo, anulando el paso de medida:

 public class SquareImageView extends ImageView { ... @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); setMeasuredDimension(width, width); } ... } 

La otra respuesta funciona bien. Esta es solo una extensión de la solución de bertucci para hacer una vista de imagen con ancho y alto cuadrados con respecto al diseño inflado xml.

Cree una clase, digamos SquareImageView extendiendo ImageView como este,

 public class SquareImageView extends ImageView { public SquareImageView(Context context) { super(context); } public SquareImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); setMeasuredDimension(width, width); } } 

Ahora, en tu xml haz esto,

   

Si necesita que ImageView no se cree dinámicamente en el progtwig, sino que se arregle en xml, esta implementación será útil.

Aún más simple:

 public class SquareImageView extends ImageView { ... @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } } 

Varias de las respuestas anteriores son perfectamente suficientes. Solo estoy agregando una pequeña optimización a las soluciones de @Andro Selva y @ a.bertucci aquí:

Es una optimización minúscula, pero verificar que el ancho y la altura sean diferentes podría evitar otro pase de medición.

 public class SquareImageView extends ImageView { public SquareImageView(Context context) { super(context); } public SquareImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); // Optimization so we don't measure twice unless we need to if (width != height) { setMeasuredDimension(width, width); } } } 

Para aquellos que buscan una solución de Kotlin:

 class SquareImageView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 ) : ImageView(context, attrs, defStyleAttr, defStyleRes){ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) = super.onMeasure(widthMeasureSpec, widthMeasureSpec) } 

si alguien quiere que la vista no sea cuadrada, sino que tenga un tamaño proporcionalmente alto (por ejemplo, 16/9 o 1/3), puede hacerlo así:

 @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth()/3, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Un squareImageView por altura especificada:

 public class SquareImageViewByWidth extends AppCompatImageView { public SquareImageViewByWidth(Context context) { super(context); } public SquareImageViewByWidth(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageViewByWidth(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int widthMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width= getMeasuredWidth(); setMeasuredDimension(width, width); } ... } 

Un squareImageView por ancho especificado:

  public class SquareImageViewByHeight extends AppCompatImageView { public SquareImageViewByHeight(Context context) { super(context); } public SquareImageViewByHeight(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageViewByHeight(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int height = getMeasuredHeight(); setMeasuredDimension(height, height); } ... } 

Un squareImageView por mínimo de dimensiones:

 public class SquareImageViewByMin extends AppCompatImageView { public SquareImageViewByHeight(Context context) { super(context); } public SquareImageViewByHeight(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageViewByHeight(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int minSize = Math.min(width, height); setMeasuredDimension(minSize, minSize); } ... } 

Aquí todos son innecesarios llamando a su superclase para onMeasure . Aquí está mi implementación

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int size = Math.min(width, height); setMeasuredDimension(size, size); }