ImageView adjustViewBounds no funciona

Tengo un ImageView con android:layout_width=100dp , android:layout_height=wrap_content y android:adjustViewBounds=true

Su fuente es una imagen de 50 x 50 px. Pero la relación de aspecto no se conserva: la altura de ImageView es 50px, no 100px (es decir, adjustViewBounds no funciona). Si tengo una imagen de 200x200px, funciona: el ancho y la altura son 100 píxeles. Este código da como resultado una imagen de 100 px de ancho y 50 px de alto, pero la imagen de src es cuadrada:

     

El problema es que adjustViewBounds no boostá el tamaño de ImageView más allá de las dimensiones naturales del dibujable. Solo reducirá la vista para mantener la relación de aspecto; si proporciona una imagen de 500×500 en lugar de una imagen de 50×50, esto debería funcionar.

Si está interesado en el lugar donde se implementa este comportamiento, consulte la implementación onMeasure de ImageView.java .

Una solución alternativa es implementar un ImageView personalizado que cambie este comportamiento en onMeasure .

Hay una manera más simple. Haga su ImageView así:

  

De esta forma, drawable se estirará para caber en el centro de ImageView conservando la relación de aspecto. Solo tenemos que calcular la altura correcta para que sea proporcional, por lo que no tenemos ningún espacio en blanco:

 private void setImageBitmap(Bitmap bitmap, ImageView imageView){ float i = ((float)imageWidth)/((float)bitmap.getWidth()); float imageHeight = i * (bitmap.getHeight()); imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight)); imageView.setImageBitmap(bitmap); } 

Además de la respuesta de @ RomanNurik

Aquí puede encontrar una solución de trabajo, ya sea copiar o pegar el código o simplemente agregar la dependencia de Gradle

 dependencies { compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.1' } 

La solución PS proporcionada por @Nilzor no funcionó para mí

Tenía un requisito similar; en mi caso, quería que la imagen fuera cuadrada, y quería que el ImageView coincidiera con la relación de aspecto para poder usar su fondo y relleno para dibujar un borde.

Leí las respuestas aquí, pero en lugar de anular ImageView, decidí hacer un diseño que garantice que su contenido (debe ser solo una vista) sea cuadrado. De esa manera podría usar un ImageView estándar dentro de él. (Y nunca se sabe, podría querer hacer algo más cuadrado más tarde, aunque probablemente no).

En caso de que sea útil para cualquier otra persona, aquí está el código (no dude en copiarlo). Probablemente haya errores ya que solo lo hice funcionar para mi aplicación y luego me detuve. 🙂

 public class SquareLayout extends ViewGroup { public SquareLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public SquareLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SquareLayout(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // Work out width and height, and square size. int width = r - l; int height = b - t; int size, xOffset, yOffset; if(width < height) { size = width; xOffset = 0; yOffset = (height - size) / 2; } else { size = height; xOffset = (width - size) / 2; yOffset = 0; } for(int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.layout(xOffset, yOffset, size + xOffset, size + yOffset); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Get width and height. int w = -1, h = -1; switch(MeasureSpec.getMode(widthMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: w = MeasureSpec.getSize(widthMeasureSpec); break; case MeasureSpec.UNSPECIFIED: break; } switch(MeasureSpec.getMode(heightMeasureSpec)) { case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: h = MeasureSpec.getSize(heightMeasureSpec); break; case MeasureSpec.UNSPECIFIED: break; } // If only one of width/height is unspecified, set them both the same. if(w == -1 && h != -1) { w = h; } else if(h == -1 && w != -1) { h = w; } // Either they're both specified or both unspecified. int childMeasureSpec; if(w == -1) { childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } else { childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); } // Pass through to children. int maxDimension = 1; for(int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(childMeasureSpec, childMeasureSpec); maxDimension = Math.max(maxDimension, child.getMeasuredWidth()); maxDimension = Math.max(maxDimension, child.getMeasuredHeight()); } if(w == -1) { w = maxDimension; h = maxDimension; } setMeasuredDimension(w, h); } }