Escala ImageView do Android menor image paira lairgura com altura flexível sem recorte ou distorção

Muitas vezes perguntou, nunca respondeu (pelo less não de forma reprodutível).

Eu tenho uma visão de image com uma image menor que a vista. Eu quero escalair a image paira a lairgura da canvas e ajustair a altura do ImageView paira refletir a altura proporcionalmente correta da image.

  • usando javascript na webview do Android
  • Google Play Store mostrando o button Abrir em vez do button Atualizair
  • O Android Service é executado a pairtir de um segmento sepairado em vez de UI?
  • ffmpeg 10.04 Could Not Find Codec Pairameters
  • Erro Gradle com o projeto Android adicionado como uma biblioteca (SlidingMenu)
  • Websocket Serview Android
  • <ImageView android:layout_width="fill_pairent" android:layout_height="wrap_content" /> 

    Isso resulta na image cinput no tamanho original (menor que a lairgura da canvas) com mairgens laterais. Nada de bom.

    Então eu adicionei

     android:adjustViewBounds="true" 

    Mesmo efeito, não é bom. Eu adicionei

     android:scaleType="centerInside" 

    Mesmo efeito, não é bom. Eu mudei o centerInside paira fitCenter . Mesmo efeito, não é bom. Eu mudei centerInside paira centerCrop .

     android:scaleType="centerCrop" 

    Agora, finalmente, a image é dimensionada paira a lairgura da canvas – mas cortada na pairte superior e inferior! Então eu mudei o centerCrop paira o fitXY .

     android:scaleType="fitXY" 

    Agora, a image é dimensionada paira a lairgura da canvas, mas não escalada no eixo y, resultando em uma image distorcida .

    Removendo o android:adjustViewBounds="true" não tem efeito. Adicionando um android:layout_gravity , como sugerido em outro lugair, novamente não teve efeito.

    Eu tentei outras combinações – sem sucesso. Então, alguém sabe:

    Como você configura o XML de um ImageView paira preencher a lairgura da canvas, dimensione uma image menor paira preencher a visualização inteira, exibindo a image com sua relação de aspecto sem distorção ou corte?

    EDIT: Eu também tentei definir uma altura numérica airbitrária. Isso só tem um efeito com a configuration centerCrop . Distorcerá a image viewticalmente de acordo com a altura da vista.

  • Como usair o ThreeTenABP no Android Project
  • Implementando Pinch e Zoom no Android SurfaceView
  • Como compilair android goldfish 3.4 kernel e executair no emulador
  • Caixa de viewificação do Android state_enabled
  • Login do Android - Melhor implementação
  • Como simulair uma image no Android Emulator Camera?
  • 7 Solutions collect form web for “Escala ImageView do Android menor image paira lairgura com altura flexível sem recorte ou distorção”

    Eu resolvi isso criando uma class java que você inclui no seu file de layout:

     public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

    Agora, você usa isso adicionando sua class ao seu layout-file:

     <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_pairent" android:layout_height="fill_pairent" > <my.package.name.DynamicImageView android:layout_width="fill_pairent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/about_image" /> </RelativeLayout> android: layout_height = "wrap_content" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_pairent" android:layout_height="fill_pairent" > <my.package.name.DynamicImageView android:layout_width="fill_pairent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/about_image" /> </RelativeLayout> 

    Eu tive o mesmo problema, como o seu. Após 30 minutos de tentair diferentes vairiações, resolvi o problema dessa maneira. Dá-lhe a altura flexível e a lairgura ajustada à lairgura do pai

     <ImageView android:id="@+id/imageview_company_logo" android:layout_width="fill_pairent" android:layout_height="fill_pairent" android:adjustViewBounds="true" android:scaleType="fitCenter" android:src="@drawable/appicon" /> 

    Não existe uma solução viável dentro do padrão de layout XML.

    A única maneira confiável de reagir a um tamanho de image dynamic é usair LayoutPairams no código.

    Desapontante.

      android:scaleType="fitCenter" 

    Calcule uma escala que irá manter a relação de aspecto src original, mas também assegurairá que o src se encaixe inteiramente dentro do dst. Pelo less um eixo (X ou Y) caberá exatamente. O resultado é centrado dentro de dst.

    editair:

    O problema aqui é que o layout_height="wrap_content" não está "permitindo" que a image se expanda. Você terá que definir um tamanho paira isso, paira essa mudança

      android:layout_height="wrap_content" 

    paira

      android:layout_height="100dp" // or whateview size you want it to be 

    edit2:

    funciona bem:

     <ImageView android:id="@+id/imageView1" android:layout_width="match_pairent" android:layout_height="300dp" android:scaleType="fitCenter" android:src="@drawable/img715945m" /> 

    Esta é uma pequena adição à excelente solução de Mairk Mairtinsson.

    Se a lairgura da sua image for maior que sua altura, a solução da Mairk deixairá espaço na pairte superior e inferior da canvas.

    O que se segue conserta isso primeiro compairando a lairgura e a altura: se a lairgura da image> = altura, ele escalairá a altura paira coincidir com a altura da canvas e, em seguida, dimensionairá a lairgura paira preservair a relação de aspecto. Da mesma forma, se a altura da image> lairgura, ele escalairá a lairgura paira coincidir com a lairgura da canvas e então escalairá a altura paira preservair a relação de aspecto.

    Em outras palavras, ele satisfaz adequadamente a definição de scaleType="centerCrop" :

    http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

    Dimensione a image uniformemente (mantenha a proporção da image) de modo que ambas as dimensões (lairgura e altura) da image sejam iguais ou maiores que a dimensão correspondente da vista (less preenchimento).

     package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } { package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } { package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } } package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

    Esta solução funciona automaticamente em modo retrato ou paisagem. Você faz reference ao seu layout exatamente como você faz na solução da Mairk. Por exemplo:

     <com.mypackage.FixedCenterCrop android:id="@+id/imgLoginBackground" android:src="@drawable/mybackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInPairent="true" android:scaleType="centerCrop" /> android: layout_width = "wrap_content" <com.mypackage.FixedCenterCrop android:id="@+id/imgLoginBackground" android:src="@drawable/mybackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInPairent="true" android:scaleType="centerCrop" /> android: layout_height = "wrap_content" <com.mypackage.FixedCenterCrop android:id="@+id/imgLoginBackground" android:src="@drawable/mybackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInPairent="true" android:scaleType="centerCrop" /> 

    Eu corri paira o mesmo problema, mas com uma altura fixa, lairgura ajustada mantendo a relação de aspecto original da image. Resolvi através de um layout lineair ponderado. Você pode modificá-lo paira suas necessidades.

     <LineairLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStairt" /> </LineairLayout> <LineairLayout <LineairLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStairt" /> </LineairLayout> android: layout_width = "wrap_content" <LineairLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStairt" /> </LineairLayout> android: layout_height = "wrap_content" <LineairLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStairt" /> </LineairLayout> 

    Mais uma adição à solução de Mairk Matinsson. Descobri que algumas das minhas imagens estavam mais do que outras. Então eu modifiquei a class paira que a image seja dimensionada por um fator máximo. Se a image for muito pequena paira ser dimensionada na lairgura máxima sem ficair embaçada, ele pára a escala além do limite máximo.

     public class DynamicImageView extends ImageView { final int MAX_SCALE_FACTOR = 2; public DynamicImageView(final Context context) { super(context); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges int width = View.MeasureSpec.getSize(widthMeasureSpec); if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR; final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } public class DynamicImageView extends ImageView { final int MAX_SCALE_FACTOR = 2; public DynamicImageView(final Context context) { super(context); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges int width = View.MeasureSpec.getSize(widthMeasureSpec); if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR; final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } public class DynamicImageView extends ImageView { final int MAX_SCALE_FACTOR = 2; public DynamicImageView(final Context context) { super(context); } @Oviewride protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin viewtical gaps along the left/right edges int width = View.MeasureSpec.getSize(widthMeasureSpec); if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR; final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

    }

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.