2011-09-20 12 views
18

Tengo una imagen que es más pequeño que el recipiente me gustaría que se ajuste en el interior de. Me gustaría que la imagen se estire, manteniendo su relación de aspecto, hasta su mayor tamaño posible.Cómo hacer una imagen lo más grande posible, manteniendo la relación de aspecto

Para ilustrar este problema:

<ImageView android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:src="@drawable/thumbnail" 
      android:scaleType="fitXY" 
      android:adjustViewBounds="true"/> 

El ImageView supra se estira para llenar la anchura del contenedor. El @drawable Contenía sería también estirar a lo largo del eje x para adaptarse a la anchura de ImageView que es perfecto. El problema sin embargo es que la dimensión etiquetada wrap_content, en este caso la altura, sigue siendo el mismo tamaño que el @drawable s altura inicial.

He leído la documentación relativa a ScaleType here y no puedo encontrar la respuesta allí.

La imagen siguiente describe el código anterior:

enter image description hereenter image description here

Current behaviour    Desired Behaviour 

Editar

Un ImageView dado scaleType="fitCenter" ampliará con precisión/reducir la @drawable dentro de ella para crecer lo más grande posible mientras reten ing es su relación de aspecto.

El ImageView s dimensiones se definen antes de la @drawable se escala de ninguna manera. Las dimensiones ImageView no se ven afectadas por la escala de su contenido @drawable.

+2

Para mí, esto es un problema común, uno para el que nunca he encontrado una solución limpia. Agregue un parche de fondo de 9 para un marco, y es aún peor intentarlo y corregirlo. Estoy bastante seguro de que esto es algo que tendrá que hacer programáticamente, pero sería bueno si alguien tiene una solución para esto. – kcoppock

+2

+1 para una pregunta completamente descrita – Merlin

Respuesta

7

XML

La única solución a este en XML es utilizar "match_parent" o un valor máximo discreta en lugar de "wrap_content" donde sea posible. Esto asegurará que el ImageView es el tamaño correcto, que a su vez significa la adición de scaleType="fitCenter" asegurará la @drawable luego se escala correctamente.

Programatically

Es feo, pero se puede cambiar el tamaño de la ImageView después de que las dimensiones se han dado valores discretos:

final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail); 

    ViewTreeObserver thumbnailViewVto = thumbnailView.getViewTreeObserver(); 
    thumbnailViewVto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     private boolean changed = false; 
     @Override 
     public void onGlobalLayout() { 
      if(!changed) { 
       Drawable image = getResources().getDrawable(R.drawable.thumbnail); 
       float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight(); 
       int height = thumbnailView.getHeight(); 

       thumbnailView.setLayoutParams(
         new LayoutParams(
           (int) (height * heighToWidthRatio), height)); 
       changed = true; 
      } 
     } 
    }); 

EDITAR

final ImageView thumbnailView = (ImageView) toReturn.findViewById(R.id.thumbnail); 

    thumbnailView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 

     @Override 
     public void onGlobalLayout() { 
      // Remove the GlobalOnLayout Listener so it only fires once. 
      thumbnailView.getViewTreeObserver().removeGlobalOnLayoutListener(this) 

      // Find the images Height to Width ratio 
      Drawable image = getResources().getDrawable(R.drawable.thumbnail); 
      float heighToWidthRatio = image.getIntrinsicWidth()/image.getIntrinsicHeight(); 

      // Use this ratio to discover the ratio of the ImageView to allow it to perfectly contain the image. 
      int height = thumbnailView.getHeight(); 
      thumbnailView.setLayoutParams(new LayoutParams(
           (int) (height * heighToWidthRatio), height)); 
     } 
    }); 
+1

+1 para resolver un problema común – Merlin

+0

¿Para qué es booleano 'changed'? – BornToCode

+0

Es así que el oyente onGlobalLayout no se activa repetidamente. Más viejo y más sabio, ahora simplemente eliminaría el 'OnGlobalLayoutListener' del' ViewTreeObserver' como la primera acción en el método 'onGlobalLayout()'. (Ver mi edición para más detalles) – Graeme

1

Parece que desea fitCenter, que utiliza Matrix.ScaleToFit CENTER.

+0

Esto mantiene la relación de aspecto pero la imagen ya no se llena.Esto funcionaría si la altura de ImageView fuera correcta, lo cual se puede hacer programáticamente, pero me gustaría que ocurriera a través de XML. – Graeme

+0

@Graeme - Desde el enlace: "Calcule una escala que mantenga la relación de aspecto src original, pero también se asegurará de que src encaje por completo dentro de dst. * Al menos un eje (X o Y) se ajustará exactamente. * El resultado es centrado en el interior de dst ". - Su descripción parece implicar que la imagen se estirará para rellenar el ancho o la altura. ¿Tal vez solo se encoge para caber, pero no se estira para encajar? – mbeckish

+0

Esa descripción es exactamente correcta, ya que una de las dimensiones está configurada en "wrap_content" pero la inicialización de tamaño de ImageView parece ocurrir antes de la escala, por lo tanto, la altura de View ya está configurada y está utilizando el eje más pequeño para ajustarse a sin agrandarlo – Graeme

Cuestiones relacionadas