¿Cómo alinear ImageView a la parte inferior, llenar su ancho y altura, y mantener su relación de aspecto?

Fondo

Existen varios atributos XML para que ImageView pueda escalar su contenido y varias vistas de diseño que permiten colocar vistas y establecer sus tamaños.

Sin embargo, no puedo averiguar cómo escalar una imagen muy bien en algunos casos.

Un ejemplo de ello es poner el ImageView en la parte inferior (de un frameLayout, por ejemplo), escalar su ancho tanto como sea posible, y mantener la relación de aspecto (sin recortar).

El problema

Ninguna de las combinaciones que he encontrado funcionó, incluyendo varios valores de ScaleType, adjustViewBounds, gravedad, …

Parece que ImageView pierde algunos valores importantes de ScaleType.

Lo que he intentado

Hasta ahora, la única solución que funcionó para mí, es establecer la imageView en la parte inferior (usando la gravedad ajustada en la parte inferior y en el centro-horizontal) y usar código similar a esto:

final ImageView logoBackgroundImageView = ...; final LayoutParams layoutParams = logoBackgroundImageView.getLayoutParams(); final Options bitmapOptions = ImageService.getBitmapOptions(getResources(), R.drawable.splash_logo); final int screenWidth = getResources().getDisplayMetrics().widthPixels; layoutParams.height = bitmapOptions.outHeight * screenWidth / bitmapOptions.outWidth; logoBackgroundImageView.setLayoutParams(layoutParams); 

Esto normalmente funciona, y no necesita muchos cambios para que funcione cuando no está en pantalla completa, pero me pregunto si hay una forma más sencilla.

Es posible que no funcione en caso de que la altura llegue a ser demasiado grande, por lo que es posible que desee cambiarlo para que si eso sucede, se establece el ancho a ser más pequeño para permitir que todo se ajuste al contenedor.

La pregunta

¿Existe una solución o una biblioteca que corrige los diversos problemas relacionados con ImageView?


EDIT: aquí hay una imagen de muestra de lo que estoy tratando de hacer, esta vez, dentro de un LinearLayout vertical que limita el ImageView en el medio, entre otras 2 vistas:

Introduzca aquí la descripción de la imagen

Como puede ver, en algunas (o todas?) De las vistas previas, la imagen central está alineada a la derecha en lugar de permanecer en el centro (horizontal).

Quiero que tome todo el espacio que tiene y escala (manteniendo relación de aspecto), y aún así estar alineado a la parte inferior del espacio que tiene.

Aquí hay un ejemplo de XML de una combinación que he probado:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF339AE2"> <View android:layout_width="match_parent" android:id="@+id/topView" android:layout_alignParentTop="true" android:layout_height="100dp" android:background="#FF00ff00" /> <FrameLayout android:layout_below="@+id/topView" android:layout_width="match_parent" android:layout_centerHorizontal="true" android:layout_above="@+id/bottomView" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:background="#FFffff00" android:layout_gravity="bottom|center_horizontal" android:src="@android:drawable/sym_def_app_icon" android:scaleType="fitEnd" android:layout_height="match_parent" /> </FrameLayout> <View android:background="#FFff0000" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:id="@+id/bottomView" android:layout_width="match_parent" android:layout_height="100dp"/> </RelativeLayout> 

Nuevamente, tenga en cuenta que he probado varias combinaciones, pero ninguna funcionó, por lo que si sugiere algo que cambiar en XML, pruebe primero. También tenga en cuenta que lo anterior es un POC (para que sea fácil de leer).

BTW, la solución que he sugerido funciona en algunos (o más?) Casos, pero no todos. Se puede notar simplemente girando el dispositivo. Tal vez hay una manera de solucionarlo, o ampliar desde ImageView para proporcionar el caso extra.

Necesita una combinación de tres atributos:

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

El atributo adjustViewBounds es necesario porque ImageView mide por sí mismo para coincidir con las dimensiones originales del dibujable por defecto, sin tener en cuenta la escala realizada de acuerdo con el tipo de escala.

Puede utilizar es personalizado FitWidthAtBottomImageView para lograr este código:

 public class FitWidthAtBottomImageView extends ImageView { public FitWidthAtBottomImageView(Context context) { super(context); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs) { super(context, attrs); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public FitWidthAtBottomImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onDraw(Canvas canvas) { int i = getWidth() - getPaddingLeft() - getPaddingRight(); int j = getHeight() - getPaddingTop() - getPaddingBottom(); if (getBackground() != null) { getBackground().draw(canvas); } if (getDrawable() != null && getDrawable() instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) getDrawable()).getBitmap(); int h = bitmap.getHeight() * i / bitmap.getWidth(); canvas.drawBitmap(bitmap, null, new RectF(getPaddingLeft(), getPaddingTop() + j - h, getPaddingLeft() + i, getHeight() - getPaddingBottom()), null); } else { super.onDraw(canvas); } } } 

Dibuje manualmente la imagen alineada inferior que desee.

Se trata de una prueba de om-concepto personalizado ImageView, tendrá que agregar los constructores que faltan y realizar el ajuste de Matrix siempre que ImageView de Drawable cambia:

 class V extends ImageView { public V(Context context) { super(context); setScaleType(ScaleType.MATRIX); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Drawable d = getDrawable(); if (d != null) { Matrix matrix = new Matrix(); RectF src = new RectF(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); RectF dst = new RectF(0, 0, w, h); matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER); float[] points = { 0, d.getIntrinsicHeight() }; matrix.mapPoints(points); matrix.postTranslate(0, h - points[1]); setImageMatrix(matrix); } } } 

Cómo funciona en breve:

  • Primero la matriz se establece llamando Matrix.setRectToRect() con stf == Matrix.ScaleToFit.CENTER , el resultado es el mismo que ImageView.ScaleType.FIT_CENTER

  • Entonces con el fin de alinear el Drawable a la Matrix.mapPoints() inferior Matrix.mapPoints() se llama, se asigna la esquina izquierda / inferior del Drawable y el resultado se transforma punto como se vería en el ImageView

  • Y finalmente Matrix.postTranslate() traduce el MAtrix en el eje Y al fondo de ImageView

Trate de usar android:scaleType="fitCenter"

Editar

Hm, vi lo que quieres decir, otra opción es fitEnd en el xml de retrato y crear un xml idéntico en la carpeta de diseño de la tierra (crear si es necesario) con android:scaleType="fitCenter" que se utilizará sólo en el paisaje

He utilizado android: scaleType = "fitXY", pero me hizo intentarlo tantas veces hasta que la imagen se puso en forma el XY de toda la pantalla ,,, lo que quiero decir que hay un error extraño en scaleType y fitEnd funcionará bien, pero usted Necesitará borrarlo y volver a escribirlo hasta que encaje en el final de cualquier pantalla sin corregir. Bottom line scaleType tiene bugs y bugs hasta que te da lo que necesitas.

Puño de todos, realmente no entiendo lo que realmente quieres para alinear la imagen a la parte inferior de lo que leo su diseño. Mi diseño hará que el centro de la imagen, y la escala que puede modificar la parte superior de la vista inferior para ver cómo se verá la imagen. Cambie la parte superior de la vista superior o inferior el tamaño de la imagen aumentará o disminuirá según el espacio disponible para imageView.

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:id="@+id/topView" android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentTop="true" android:background="#FF00ff00" /> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/bottomView" android:layout_below="@+id/topView"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" android:background="#FFffff00" android:scaleType="fitCenter" android:src="@android:drawable/sym_def_app_icon" /> </FrameLayout> <View android:id="@+id/bottomView" android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="#FFff0000" /> </RelativeLayout> 

Espero que esto solucione su problema.

  • Cómo convertir un objeto de imagen en un objeto de mapa de bits, Android
  • Android tutorial de procesamiento de imágenes?
  • Mapa de bits en Android: Tamaño de los recursos para mostrar como 50dp
  • (Java LibGDX) ¿Cómo puedo cambiar el tamaño de mis texturas en LibGDX?
  • ¿Cómo enviar múltiples imágenes de las que están presentes en la carpeta de la unidad de google en android mediante programación?
  • Añadir marca de agua pequeña imagen a gran imagen opencv4android
  • Posicionamiento de una imagen dentro de un ImageView con gravedad: arriba
  • Tamaño de fondo de la imagen de la actividad de Android
  • ¿Cómo mantener una imagen en una actividad de Android durante un cambio de orientación?
  • Picture.writeToStream () no escribiendo todos los mapas de bits
  • Colocar la imagen en las coordenadas de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.