Como dimensionar uma imagem no ImageView para manter a proporção

526

Em Android, eu definido um ImageViewé layout_widthpara ser fill_parent(que ocupa toda a largura do telefone).

Se a imagem que eu coloco ImageViewfor maior que a layout_width, o Android a dimensionará, certo? Mas e a altura? Quando o Android dimensiona a imagem, ele mantém a proporção?

O que eu descobri é que há algum espaço em branco na parte superior e inferior do ImageViewquando o Android dimensiona uma imagem que é maior que a ImageView. Isso é verdade? Se sim, como posso eliminar esse espaço em branco?

Michael
fonte

Respostas:

799
  1. Sim, por padrão, o Android redimensionará sua imagem para caber no ImageView, mantendo a proporção. No entanto, verifique se você está configurando a imagem para o ImageView usando, em android:src="..."vez de android:background="...". src=faz com que ela dimensione a imagem mantendo a proporção, mas background=a escala e distorce a imagem para ajustá-la exatamente ao tamanho do ImageView. (Você pode usar um plano de fundo e uma fonte ao mesmo tempo, o que pode ser útil para exibir um quadro ao redor da imagem principal, usando apenas um ImageView.)

  2. Você também deve ver android:adjustViewBounds fazer o redimensionamento do ImageView para se ajustar à imagem redimensionada. Por exemplo, se você tiver uma imagem retangular no que normalmente seria um ImageView quadrado, AdjustViewBounds = true fará com que redimensione o ImageView para ser retangular também. Isso afeta como outras visualizações são dispostas em torno do ImageView.

    Então, como Samuh escreveu, você pode alterar a maneira como o padrão escala as imagens usando o android:scaleTypeparâmetro A propósito, a maneira mais fácil de descobrir como isso funciona seria simplesmente experimentar um pouco! Lembre-se de olhar os layouts no próprio emulador (ou em um telefone real), pois a visualização no Eclipse geralmente está errada.

Steve Haley
fonte
18
É a mesma coisa, apenas feita em código, e não em XML. setImageBitmapé o mesmo que android:src="..."e setBackground...éandroid:background="..."
Steve Haley
4
@SuperUser também image.setImageDrawable(...)está android:src="..."em xml.
PureSpider
11
"android: AdjustViewBounds" é o mais útil aqui para anotar! se você não adicionar isso, provavelmente terá problemas com a borda / limites / contêiner do ImageView não sendo dimensionados corretamente.
irritada 84
2
src = vs background = foi a diferença para mim!
Christopher Rathgeb
21
android:adjustViewBoundsfoi a última peça do meu quebra-cabeça, obrigado!
precisa
281

Veja android:adjustViewBounds.

Defina como true se desejar que o ImageView ajuste seus limites para preservar a proporção da sua gaveta.

Gratzi
fonte
6
Esta é a correção correta para o problema. Estávamos vendo isso na visualização da imagem, onde a altura incluía todo esse espaço em branco extra. Não são "pixels transparentes", pois tivemos fill_parent para largura e wrap_content para altura. Se você não tiver AdjustViewBounds = true, receberá o espaço em branco extra. Depois de definir isso como verdadeiro, nosso problema desapareceu. Obrigado!
Christophercotton
3
obrigado, e configurá-lo para src em vez de segundo plano funcionou perfeitamente!
Cameron
Veja também como dimensionar o bitmap para o tamanho da tela
ThomasRS 11/12/12
1
Essa é a correção perfeita para o problema. Também para os tamanhos, use o contêiner pai para definir o tamanho e defina match_parent no ImageView. Isso resolve muitos problemas.
Nimila Hiranya
+1 para chegar ao ponto. Inicialmente, escrevi isso em uma frase mais "coloquial" e me impediu de enviá-la. Em vez de plumas plissadas, um PC foi.
23916 Jacksonkr
168

Para qualquer pessoa que tenha esse problema em particular. Você tem uma ImageViewlargura fill_parente uma altura dimensionadas proporcionalmente:

Adicione estes dois atributos ao seu ImageView:

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

E defina a ImageViewlargura fill_parente a altura como wrap_content.

Além disso, se você não deseja que sua imagem seja cortada, tente o seguinte:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Kevin Parker
fonte
16
Sim, mas sua imagem é cortada. A solução perfeita se estenderia à largura, manteria a proporção e não cortaria. Eu não tenho idéia do por que isso tem que ser tão difícil de fazer ...
Warpzit
1
Nem eu :( Desculpe se minha solução não ajudá-lo, mas ele me ajudou.
Kevin Parker
2
Kevin, o que você disse foi exatamente o que eu estava procurando, se o tamanho da imagem for menor que o da tela, ela será ampliada e centralizada, perfeita. Obrigado.
Soham 17/01
1
+1, exceto "(ou outro View)". AFAICT nenhuma outra visualização possui adjustViewBoundsou scaleTypeatributos.
LarsH 08/09
que tal usar android: scaleType = "centerInside" em vez de android: scaleType = "centerCrop"? Também não cortaria a imagem, mas garantiria que largura e altura sejam iguais ou inferiores à largura e altura da visualização de imagem :) Aqui está um bom guia visual para tipos de escalonamento: thoughtbot.com/blog/android-imageview-scaletype-a-visual- guide
vida
57

Se você deseja um ImageViewque seja dimensionado para cima e para baixo, mantendo a proporção adequada, adicione-o ao seu XML:

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

Adicione isto ao seu 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);

Demorei um pouco para que isso funcionasse, mas isso parece funcionar nos casos em que a imagem é menor que a largura da tela e maior que a largura da tela e não encaixa na imagem.

Kevin
fonte
1
Por que não usar apenas android: scaleType = "centerCrop"?
Lukas Batteau
funciona como um encanto, obrigado. scaleType depende da situação, por exemplo, eu precisava exatamente disso.
David
Esta é uma maneira um pouco bárbara de redimensionar a vista. O que acontece se os limites da exibição mudarem depois que você definir o bitmap para o ImageView? É por isso que isso deve ser feito em onMeasure (), que pode ser implementado se você criar uma subclasse personalizada do ImageView.
Aron Lorincz 17/03/2014
1
Tudo que eu precisava era o fitCenter e adjustViewBounds, o resto do código, pelo menos para mim era desnecessário
kingargyle
Isso funciona para mim e não precisa adicionar nenhum código. Sem o AdjustViewBounds, se a largura da imagem era menor que a largura do ImageView, ela não estava aumentando, então a altura estava parando na altura nativa e, na largura, algumas bandas apareceram.
Cristi Băluță 4/04/19
15

Isso funcionou para mim:

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

isso resolveu meu problema

android:adjustViewBounds="true"
android:scaleType="fitXY"
shafiq-ur-rehman
fonte
Não preserva a proporção da imagem para mim.
Dmitry
9

Abaixo do código Trabalhando para a imagem em escala como proporção:

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
fonte
8

Dê uma olhada no ImageView.ScaleType para controlar e entender como o redimensionamento acontece em um ImageView. Quando a imagem é redimensionada (mantendo a proporção), as chances são de que a altura ou a largura da imagem se tornem menores que ImageViewas dimensões.

Samuh
fonte
6

Use estas propriedades no ImageView para manter a proporção:

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
fonte
Somente essa resposta me ajudou. Obrigado!
Dmitry
6

É assim que funcionou para mim dentro de um ConstraintLayout:

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

Em seguida, no código, defino o drawable como:

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

Isso se ajusta bem à imagem, de acordo com sua proporção e a mantém no centro.

Jeet
fonte
5

Eu tenho uma imagem menor que a tela. Para esticá-lo proporcionalmente ao máximo e centralizado na visualização, tive que usar o seguinte 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" />

No entanto, lembre-se de que, se você tiver um layout relativo e alguns elementos definidos acima ou abaixo do ImageView, eles provavelmente serão sobrepostos pela imagem.

halxinato
fonte
4

Se a qualidade da imagem diminuir em: use

android:adjustViewBounds="true"

ao invés de

android:adjustViewBounds="true"
android:scaleType="fitXY"
developerSumit
fonte
3

Para quem deseja que a imagem se ajuste exatamente à visualização de imagem com o dimensionamento adequado e sem uso de recorte

imageView.setScaleType(ScaleType.FIT_XY);

onde imageView é a visualização que representa seu ImageView

oneConsciousness
fonte
4
Não, isso muda a proporção do aspecto. Os documentos dizem: "Dimensione em X e Y independentemente, para que o src corresponda exatamente ao dst. Isso pode alterar a proporção do src."
Rose Perrone 28/05
A propósito, este FIT_XY não pode ser usado para alterar a largura / altura da imagem para exibição na visualização de imagem.
Bay
3

Você pode calcular a largura da tela. E você pode escalar bitmap.

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

calcular a largura da tela e a altura da imagem em escala pela largura da tela.

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

Depois que você pode dimensionar o bitmap.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
android_developer
fonte
3

Ao fazer isso programaticamente, chame os setters na ordem correta:

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

Se você deseja que sua imagem ocupe o espaço máximo possível, a melhor opção seria

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

Você não precisa de nenhum código java. Você só tem de :

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

A chave está no pai de correspondência para largura e altura

Romu Dizzy
fonte
1

Tente usar o android:layout_gravityImageView:

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

O exemplo acima funcionou para mim.

ITisha
fonte
1
android: layout_weight = "1" é a chave.
Nima
1

Eu tenho um algoritmo para dimensionar um bitmap para melhor ajustar as dimensões do contêiner, mantendo sua proporção. Encontre minha solução aqui

Espero que isso ajude alguém na estrada!

Parth Kapoor
fonte
0

Eu uso isso:

<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
fonte
0

no caso de usar cardviewpara arredondamento imageviewe fixo android:layout_heightpara cabeçalho, isso funcionou para mim carregar a imagem comGlide

    <?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
fonte
0

Você pode dimensionar a imagem que também reduzirá o tamanho da sua imagem. Existe uma biblioteca para você baixar e usar. https://github.com/niraj124124/Images-Files-scale-and-compress.git

Como usar 1) Importe o compressor-v1.0. jar para o seu projeto. 2) Adicione o código de amostra abaixo para testar. ResizeLimiter resize = ImageResizer.build (); resize.scale ("inputImagePath", "outputImagePath", imageWidth, imageHeight); Muitos outros métodos existem de acordo com sua exigência

Niraj
fonte
0

Passe seu ImageView e, com base na altura e largura da tela, você poderá

    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
fonte
0

Resposta 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
fonte
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
user2099162
fonte