Cómo escalar una imagen en ImageView para mantener la relación de aspecto

526

En Android, he definido un ImageView's layout_widthde ser fill_parent(que ocupa todo el ancho del teléfono).

Si la imagen que coloco ImageViewes más grande que la de layout_widthAndroid, la escalará, ¿verdad? ¿Pero qué hay de la altura? Cuando Android escala la imagen, ¿mantendrá la relación de aspecto?

Lo que descubrí es que hay un espacio en blanco en la parte superior e inferior de ImageViewcuando Android escala una imagen que es más grande que la ImageView. ¿Es eso cierto? En caso afirmativo, ¿cómo puedo eliminar ese espacio en blanco?

Miguel
fuente

Respuestas:

799
  1. Sí, de manera predeterminada, Android reducirá su imagen para que se ajuste a ImageView, manteniendo la relación de aspecto. Sin embargo, asegúrese de configurar la imagen en ImageView usando en android:src="..."lugar de android:background="...". src=lo hace escalar la imagen manteniendo la relación de aspecto, pero lo background=hace escalar y distorsionar la imagen para que se ajuste exactamente al tamaño de ImageView. (Sin embargo, puede usar un fondo y una fuente al mismo tiempo, lo que puede ser útil para cosas como mostrar un marco alrededor de la imagen principal, usando solo un ImageView).

  2. También debería ver android:adjustViewBoundsque ImageView se redimensione para adaptarse a la imagen reescalada. Por ejemplo, si tiene una imagen rectangular en lo que normalmente sería un ImageView cuadrado, ajusteViewBounds = true hará que cambie el tamaño del ImageView para que también sea rectangular. Esto entonces afecta la forma en que se presentan otras Vistas alrededor de ImageView.

    Luego, como escribió Samuh, puede cambiar la forma en que las escalas predeterminadas usan el android:scaleTypeparámetro. Por cierto, ¡la forma más fácil de descubrir cómo funciona esto habría sido experimentar un poco usted mismo! Solo recuerde mirar los diseños en el emulador mismo (o en un teléfono real) ya que la vista previa en Eclipse generalmente es incorrecta.

Steve Haley
fuente
18
Eso es lo mismo, solo hecho en código en lugar de XML. setImageBitmapes lo mismo android:src="..."y setBackground...esandroid:background="..."
Steve Haley
44
@SuperUser también image.setImageDrawable(...)está android:src="..."en xml.
PureSpider
11
"Android: ajustarViewBounds" es el útil aquí para tener en cuenta. Si no agrega esto, lo más probable es que tenga problemas con el borde / límite / contenedor de ImageView que no se escala correctamente.
Enojado 84
2
¡src = vs background = fue la diferencia para mí!
Christopher Rathgeb
21
android:adjustViewBoundsfue la última pieza de mi rompecabezas, gracias!
themarketka
281

Ver android:adjustViewBounds.

Establezca esto en verdadero si desea que ImageView ajuste sus límites para preservar la relación de aspecto de su dibujo.

Gratzi
fuente
66
Esta es la solución correcta para el problema. Teníamos esto en nuestra vista de imagen, donde la altura incluía todo este espacio en blanco adicional. No son "píxeles transparentes", ya que teníamos fill_parent para ancho y wrap_content para alto. Si no tiene AdjustViewBounds = true, obtendrá el espacio en blanco adicional. Después de establecer eso en verdadero, nuestro problema desapareció. ¡Gracias!
christophercotton
3
gracias, esto y configurarlo en src en lugar de fondo funcionó perfectamente!
Cameron
1
Esta es la solución perfecta para el problema. También para los tamaños, use el contenedor principal para establecer el tamaño y establezca match_parent en ImageView. Esto resuelve muchos problemas.
Nimila Hiranya
+1 para llegar al punto. Inicialmente escribí eso en una frase más "coloquial" y sof me prohibió enviarlo. En lugar de volantes plumas una PC fue.
Jacksonkr
168

Para cualquier otra persona que tenga este problema en particular. Tiene un valor del ImageViewque desea tener un ancho fill_parenty una altura escalados proporcionalmente:

Agregue estos dos atributos a su ImageView:

android:adjustViewBounds="true"
android:scaleType="centerCrop"

Y establezca el ImageViewancho fill_parenty la altura en wrap_content.

Además, si no desea que se recorte su imagen, intente esto:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Kevin Parker
fuente
16
Sí, pero tu imagen se recorta. La solución perfecta se estiraría al ancho, mantendría la relación de aspecto y no se recortaría. No tengo ni idea de por qué esto tiene que ser así anoing que hacer ...
Warpzit
1
Yo tampoco :( Lo siento si mi solución no te ayudó, pero sí me ayudó.
Kevin Parker
2
Kevin, lo que dijiste era exactamente lo que estaba buscando, si el tamaño de la imagen es menor que el de la pantalla, se amplía y se centra, perfecto. Gracias.
Soham
1
+1, excepto "(u otro View)". AFAICT ninguna otra vista tiene adjustViewBoundso scaleTypeatributos.
LarsH
¿Qué tal usar android: scaleType = "centerInside" en lugar de android: scaleType = "centerCrop"? Tampoco recortaría la imagen, pero aseguraría que tanto el ancho como la altura sean menores o iguales que el ancho y la altura de la vista de imagen :) Aquí hay una buena guía visual para los tipos de escala: thoughtbot.com/blog/android-imageview-scaletype-a-visual- guía
vida
57

Si desea ImageViewque ambas escalen hacia arriba y hacia abajo manteniendo la relación de aspecto adecuada, agregue esto a su XML:

android:adjustViewBounds="true"
android:scaleType="fitCenter"

Agregue esto a su código:

// We need to adjust the height if the width of the bitmap is
// smaller than the view width, otherwise the image will be boxed.
final double viewWidthToBitmapWidthRatio = (double)image.getWidth() / (double)bitmap.getWidth();
image.getLayoutParams().height = (int) (bitmap.getHeight() * viewWidthToBitmapWidthRatio);

Me tomó un tiempo hacer que esto funcionara, pero parece funcionar en los casos en que la imagen es más pequeña que el ancho de la pantalla y más grande que el ancho de la pantalla, y no encajona la imagen.

Kevin
fuente
1
¿Por qué no usar Android: scaleType = "centerCrop"?
Lukas Batteau
funciona como un encanto, gracias. scaleType depende de la situación, por ejemplo, necesitaba exactamente esto.
David
Esta es una forma un poco bárbara de cambiar el tamaño de la vista. ¿Qué sucede si los límites de la vista cambian después de establecer el mapa de bits en ImageView? Es por eso que debe hacerse en onMeasure (), que puede implementarse si crea una subclase personalizada de ImageView.
Aron Lorincz
1
Todo lo que necesitaba era fitCenter y ajustarViewBounds, el resto del código, al menos para mí, era innecesario
Kingargyle
Esto funciona para mí y no necesito agregar ningún código. Sin el ajusteViewViewBounds si el ancho de la imagen era más pequeño que el ancho de la vista de imagen, no se estaba ampliando, por lo que la altura se detenía a la altura nativa y en el ancho aparecieron algunas bandas.
Cristi Băluță
15

Esto funcionó para mí:

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"
Mike6679
fuente
10

esto resolvió mi problema

android:adjustViewBounds="true"
android:scaleType="fitXY"
shafiq-ur-rehman
fuente
No conserva la relación de aspecto de la imagen para mí.
Dmitry
9

Debajo del código Trabajando para escalar la imagen como relación de aspecto:

Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
Mukesh Parmar
fuente
8

Eche un vistazo a ImageView.ScaleType para controlar y comprender la forma en que se realiza el cambio de tamaño en un ImageView. Cuando se cambia el tamaño de la imagen (manteniendo su relación de aspecto), es probable que la altura o el ancho de la imagen sean más pequeños que ImageViewlas dimensiones.

Samuh
fuente
6

Use estas propiedades en ImageView para mantener la relación de aspecto:

android:adjustViewBounds="true"
android:scaleType="fitXY"

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
Atif Mahmood
fuente
Solo esta respuesta me ayudó. ¡Gracias!
Dmitry
6

Así es como funcionó para mí dentro de un RestraintLayout:

<ImageView
    android:id="@+id/myImg"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"/>

Luego, en el código, configuré el dibujable como:

ImageView imgView = findViewById(R.id.myImg);
imgView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.image_to_show, null));

Esto se adapta muy bien a la imagen según su relación de aspecto y la mantiene en el centro.

Jeet
fuente
5

Tengo una imagen más pequeña que la pantalla. Para extenderlo proporcionalmente al máximo y centrarlo en la vista, tuve que usar el siguiente código:

<ImageView
    android:id="@+id/my_image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:layout_weight="1"
    android:scaleType="fitCenter" />

Sin embargo, tenga en cuenta que si tiene un diseño relativo y tiene algunos elementos configurados para estar por encima o por debajo de ImageView, lo más probable es que se superpongan con la imagen.

halxinato
fuente
4

Si la calidad de la imagen disminuye en: uso

android:adjustViewBounds="true"

en vez de

android:adjustViewBounds="true"
android:scaleType="fitXY"
desarrolladorSumit
fuente
3

Para cualquiera de ustedes que quiera que la imagen se ajuste exactamente a la vista de la imagen con la escala adecuada y sin uso de recorte

imageView.setScaleType(ScaleType.FIT_XY);

donde imageView es la vista que representa su ImageView

oneConsciousness
fuente
44
No, esto cambia la relación de aspecto. Los documentos dicen: "Escale en X e Y independientemente, de modo que src coincida exactamente con dst. Esto puede cambiar la relación de aspecto del src".
Rose Perrone
Por cierto, este FIT_XY no se puede usar para cambiar el ancho / alto de la imagen para mostrarla en la vista de imagen.
Bahía
3

Puedes calcular el ancho de la pantalla. Y puedes escalar el mapa de bits.

 public static float getScreenWidth(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        float pxWidth = outMetrics.widthPixels;
        return pxWidth;
    }

calcule el ancho de pantalla y la altura de la imagen a escala por el ancho de la pantalla

float screenWidth=getScreenWidth(act)
  float newHeight = screenWidth;
  if (bitmap.getWidth() != 0 && bitmap.getHeight() != 0) {
     newHeight = (screenWidth * bitmap.getHeight()) / bitmap.getWidth();
  }

Después de que pueda escalar el mapa de bits.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
desarrollador de Android
fuente
3

Al hacer esto programáticamente, asegúrese de llamar a los setters en el orden correcto:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
lukas
fuente
2

Si desea que su imagen ocupe el máximo espacio posible, entonces la mejor opción sería

android:layout_weight="1"
android:scaleType="fitCenter"
Mohsen Afshin
fuente
2

No necesitas ningún código java. Sólo tienes que :

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />

La clave está en el elemento primario coincidente para ancho y alto

Romu Dizzy
fuente
1

Intente usar android:layout_gravitypara ImageView:

android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="1"

El ejemplo anterior funcionó para mí.

ITisha
fuente
1
android: layout_weight = "1" es la clave.
nima
1

Tengo un algoritmo para escalar un mapa de bits para que se ajuste mejor a las dimensiones del contenedor, manteniendo su relación de aspecto. Encuentra mi solución aquí

Espero que esto ayude a alguien por el camino!

Parth Kapoor
fuente
0

Yo uso esto:

<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:scaleType="centerInside"
android:src="@drawable/logo" />
Flavio Capaccio
fuente
0

en caso de usar cardviewpara redondear imageviewy corregir el android:layout_heightencabezado, esto funcionó para mí para cargar la imagen conGlide

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="220dp"
             xmlns:card_view="http://schemas.android.com/apk/res-auto"
             >

    <android.support.v7.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|top"
            card_view:cardBackgroundColor="@color/colorPrimary"
            card_view:cardCornerRadius="10dp"
            card_view:cardElevation="10dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

        <ImageView
                android:adjustViewBounds="true"
                android:maxHeight="220dp"
                android:id="@+id/iv_full"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitCenter"/>

    </android.support.v7.widget.CardView>
</FrameLayout>
lvl4fi4
fuente
0

Puede escalar la imagen que también reducirá el tamaño de su imagen. Hay una biblioteca que puede descargar y usar. https://github.com/niraj124124/Images-Files-scale-and-compress.git

Cómo usar 1) Importar el compresor-v1.0. jar a su proyecto. 2) Agregue el siguiente código de muestra para probar. ResizeLimiter resize = ImageResizer.build (); resize.scale ("inputImagePath", "outputImagePath", imageWidth, imageHeight); Existen muchos más métodos de acuerdo a sus requerimientos.

Niraj
fuente
0

Pase su ImageView y, según la altura y el ancho de la pantalla, puede hacerlo

    public void setScaleImage(EventAssetValueListenerView view){
        // Get the ImageView and its bitmap
        Drawable drawing = view.getDrawable();
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
        // Get current dimensions
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float xScale = ((float) 4) / width;
        float yScale = ((float) 4) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

        Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        BitmapDrawable result = new BitmapDrawable(scaledBitmap);
        width = scaledBitmap.getWidth();
        height = scaledBitmap.getHeight();

        view.setImageDrawable(result);

        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
        params.width = width;
        params.height = height;
        view.setLayoutParams(params);
    }

ppreetikaa
fuente
0

Respuesta rápida:

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/yourImage"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
myworldbox
fuente
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
usuario2099162
fuente