Escala de imagen para llenar el ancho de ImageView y mantener la relación de aspecto

Tengo un GridView . Los datos de GridView se solicitan desde un servidor.

Aquí está el diseño del elemento en GridView :

       

Solicito datos del servidor, obtengo la URL de la imagen y cargo la imagen en Bitmap

 public static Bitmap loadBitmapFromInputStream(InputStream is) { return BitmapFactory.decodeStream(is); } public static Bitmap loadBitmapFromHttpUrl(String url) { try { return loadBitmapFromInputStream((InputStream) (new URL(url).getContent())); } catch (Exception e) { Log.e(TAG, e.getMessage()); return null; } } 

y está el código del getView(int position, View convertView, ViewGroup parent) en el adaptador

 Bitmap bitmap = BitmapUtil.loadBitmapFromHttpUrl(product.getHttpUrl()); prodImg.setImageBitmap(bitmap); 

El tamaño de la imagen es 210*210 . Ejecuto mi aplicación en mi Nexus 4. La imagen llena el ancho de ImageView , pero la altura de ImageView no escala. ImageView no muestra la imagen completa.

¿Cómo resuelvo este problema?

Sin usar ninguna clase o biblioteca personalizada:

  

scaleType="fitCenter" (predeterminado cuando se omite)

  • lo hará tan ancho como lo permita el padre y subir / bajar de escala según sea necesario manteniendo la relación de aspecto.

scaleType="centerInside"

  • si el ancho intrínseco de src es más pequeño que el ancho del padre
    centrará la imagen horizontalmente
  • si el ancho intrínseco de src es mayor que el ancho del padre
    lo hará tan ancho como lo permita el padre y la relación de aspecto de mantenimiento a escala inferior.

No importa si usa los métodos android:src o ImageView.setImage* y la clave probablemente sea adjustViewBounds .

Me gusta la respuesta de arnefm, pero cometió un pequeño error (ver comentarios) que trataré de corregir:

 import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * ImageView that keeps aspect ratio when scaled */ public class ScaleImageView extends ImageView { public ScaleImageView(Context context) { super(context); } public ScaleImageView(Context context, AttributeSet attrs) { super(context, attrs); } public ScaleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { try { Drawable drawable = getDrawable(); if (drawable == null) { setMeasuredDimension(0, 0); } else { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int measuredHeight = MeasureSpec.getSize(heightMeasureSpec); if (measuredHeight == 0 && measuredWidth == 0) { //Height and width set to wrap_content setMeasuredDimension(measuredWidth, measuredHeight); } else if (measuredHeight == 0) { //Height set to wrap_content int width = measuredWidth; int height = width * drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth(); setMeasuredDimension(width, height); } else if (measuredWidth == 0){ //Width set to wrap_content int height = measuredHeight; int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight(); setMeasuredDimension(width, height); } else { //Width and height are explicitly set (either to match_parent or to exact value) setMeasuredDimension(measuredWidth, measuredHeight); } } } catch (Exception e) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

Por lo tanto, su ImageView se escalará correctamente y no tendrá problemas de dimensión si (por ejemplo) se coloca dentro de ScrollView

Tuve un problema similar una vez. Lo resolví haciendo un ImageView personalizado.

 public class CustomImageView extends ImageView 

A continuación, anule el método onMeasure de la vista de la imagen. Hice algo como esto, creo:

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { try { Drawable drawable = getDrawable(); if (drawable == null) { setMeasuredDimension(0, 0); } else { float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight(); float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec); if (imageSideRatio >= viewSideRatio) { // Image is wider than the display (ratio) int width = MeasureSpec.getSize(widthMeasureSpec); int height = (int)(width / imageSideRatio); setMeasuredDimension(width, height); } else { // Image is taller than the display (ratio) int height = MeasureSpec.getSize(heightMeasureSpec); int width = (int)(height * imageSideRatio); setMeasuredDimension(width, height); } } } catch (Exception e) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

Esto estirará la imagen para que se ajuste a la pantalla mientras mantiene la relación de aspecto.

Use android:scaleType="centerCrop" .

Hice algo similar a lo anterior y luego me golpeé la cabeza contra la pared durante unas horas porque no funcionó dentro de RelativeLayout . Terminé con el siguiente código:

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

Y luego, para evitar que RelativeLayout ignore la dimensión medida, hice esto:

     

Esto no será aplicable si establece la imagen como fondo en ImageView, necesita establecer en src (android: src).

Gracias.

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

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

Puede intentar hacer lo que hace manualmente cargando las imágenes, pero recomiendo encarecidamente echar un vistazo a Universal Image Loader .

Recientemente lo integé en mi proyecto y debo decir que es fantástico. ¿Te preocupa todo lo relacionado con hacer que las imágenes sean asíncronas, redimensionadas y almacenadas en caché por ti? Es muy fácil de integrar y configurar. Dentro de los 5 minutos, probablemente pueda hacerlo haciendo lo que quiera.

Código de ejemplo:

 //ImageLoader config DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder().showStubImage(R.drawable.downloadplaceholder).cacheInMemory().cacheOnDisc().showImageOnFail(R.drawable.loading).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()). defaultDisplayImageOptions(displayimageOptions).memoryCache(new WeakMemoryCache()).discCache(new UnlimitedDiscCache(cacheDir)).build(); if (ImageLoader.getInstance().isInited()) { ImageLoader.getInstance().destroy(); } ImageLoader.getInstance().init(config); imageLoadingListener = new ImageLoadingListener() { @Override public void onLoadingStarted(String s, View view) { } @Override public void onLoadingFailed(String s, View view, FailReason failReason) { ImageView imageView = (ImageView) view; imageView.setImageResource(R.drawable.android); Log.i("Failed to Load " + s, failReason.toString()); } @Override public void onLoadingComplete(String s, View view, Bitmap bitmap) { } @Override public void onLoadingCancelled(String s, View view) { } }; //Imageloader usage ImageView imageView = new ImageView(getApplicationContext()); if (orientation == 1) { imageView.setLayoutParams(new LinearLayout.LayoutParams(width / 6, width / 6)); } else { imageView.setLayoutParams(new LinearLayout.LayoutParams(height / 6, height / 6)); } imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageLoader.displayImage(SERVER_HOSTNAME + "demos" + demo.getPathRoot() + demo.getRootName() + ".png", imageView, imageLoadingListener); 

Esto puede cargar las imágenes de forma perezosa, ajustarlas correctamente al tamaño de la imagen que muestra una imagen de marcador de posición mientras se carga y mostrar un ícono predeterminado si la carga falla y el almacenamiento en caché de los recursos.

– También debería agregar que esta configuración actual mantiene la relación de aspecto de la imagen, por lo tanto, aplicable a su pregunta original

Prueba esto: resolvió el problema para mí

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

Yo no necesito ningún código de Java. Sólo tienes que :

  

La clave está en el padre del partido para el ancho y la altura

Para crear una imagen con un ancho igual al ancho de la pantalla y una altura proporcionalmente establecida de acuerdo con la relación de aspecto, haga lo siguiente.

 Glide.with(context).load(url).asBitmap().into(new SimpleTarget() { @Override public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { // creating the image that maintain aspect ratio with width of image is set to screenwidth. int width = imageView.getMeasuredWidth(); int diw = resource.getWidth(); if (diw > 0) { int height = 0; height = width * resource.getHeight() / diw; resource = Bitmap.createScaledBitmap(resource, width, height, false); } imageView.setImageBitmap(resource); } }); 

Espero que esto ayude.

intente con esta línea simple … agregue esta línea en su código xml en la etiqueta de vista de imagen sin agregar ninguna dependencia android: scaleType = “fitXY”

Usa picasso que es fácil de usar.

En tu adaptador …

 @Override public void getView(int position, View convertView, ViewGroup parent) { ImageView view = (ImageView) convertView.findViewById(R.id.ranking_prod_pic); Picasso.with(context).load(url).into(view); //url is image url //you can resize image if you want /* Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(view) */ } 

http://square.github.io/picasso/ enter image description here

Solo usa UniversalImageLoader y establece

 DisplayImageOptions.Builder() .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) .build(); 

y sin ajustes de escala en ImageView