48

¿Cómo puedo hacer que una imagen de fondo se ajuste a la vista pero mantener su relación de aspecto cuando se usa <bitmap /> como fondo xml dibujable? Ninguno de <bitmap>android:gravity valores da el efecto deseado.Imagen a escala que mantiene su relación de aspecto en el fondo dibujable

+1

ha intentado ya [ScaleType] (http://developer.android.com/reference /android/widget/ImageView.ScaleType.html)? –

+1

Pruebe android: scaleType = "matrix" – Pavandroid

+1

ScaleType es para ImageView. Los mapas de bits no lo admiten. – OldSchool4664

Respuesta

48

Es imposible lograr la manipulación del atributo de fondo solo dentro de los archivos xml. Hay dos opciones:

  1. se corta/escala del mapa de bits mediante programación con Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) y establecerla como fondo algunos View 's.

  2. Usted utilizar ImageView en lugar de fondo colocándolo como elemento de la primera disposición y especificar android:scaleType atributo para que:

    <RelativeLayout 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" > 
    
        <ImageView 
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
    
         android:src="@drawable/backgrnd" 
         android:scaleType="centerCrop" /> 
    
        ... 
    
        rest layout components here 
    
        ... 
    
    </RelativeLayout> 
    
+6

La opción 'centerCrop' de ScaleType es muy buena para esto. –

+2

Todos los posibles valores de 'android: scaleType' no dan el efecto necesario. Una imagen se ajusta a la vista manteniendo su relación de aspecto solo si no especifico 'scaleType' en absoluto. – tilex

+0

Gracias, centerInside funciona para mí. – pengguang001

3

Otro enfoque sería crear patch 9 images de su imagen regular y tienen que estirar escala de la manera que quieras.

Puede hacer que centre el contenido colocando 9 puntos de parche en las esquinas que conservarán su relación obviamente (suponiendo que el borde exterior de su imagen sea repetible/transparente).

Espero que entiendas la idea.

2

Utilizando el método descrito por a.ch funcionó muy bien para mí, si he utilizado este tipo de escala que funcionó mucho mejor de lo que necesitaba:

android:scaleType="centerCrop" 

Aquí está una lista completa de los tipos de escala disponibles: http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

+1

y aquí puedes ver algunos ejemplos para cada tipo: http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html –

29

Hay una forma fácil de hacer esto desde el dibujable:

your_drawable.xml

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 

    <item android:drawable="@color/bg_color"/> 
    <item> 
     <bitmap 
      android:gravity="center|bottom|clip_vertical" 
      android:src="@drawable/your_image" /> 
    </item> 

</layer-list> 

El único inconveniente es que si no hay suficiente espacio, su imagen no se mostrará completamente, pero se recortará, no pude encontrar una manera de hacerlo directamente desde un dibujante. Pero de las pruebas que hice funciona bastante bien, y no recorta gran parte de la imagen. Podrías jugar más con las opciones de gravedad.

Otra forma será la de simplemente crear un diseño, donde usará un ImageView y establecer el scaleType a fitCenter.

Espero que esta información lo ayude a lograr lo que desea.

1

Intenta usar InsetDrawable (funcionó bien para mí).

Simplemente déle a este su dibujo y las inserciones (o relleno) que desee de cualquiera de los cuatro lados.

InsetDrawable insetDrawable = new InsetDrawable(drawable, insetLeft, insetTop, insetRight, insetBottom); 

Se utiliza específicamente para configurar el fondo dibujable, de tamaño más pequeño o que la Vista.

ve aquí: https://developer.android.com/reference/android/graphics/drawable/InsetDrawable.html

1

vieja pregunta, pero ninguna de las otras respuestas trabajó para mí. Sin embargo este código XML hizo:

<RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <ImageView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentTop="true" 
     android:scaleType="centerCrop" 
     android:src="@drawable/background_image"/> 

</RelativeLayout> 
1

Si el mapa de bits es más ancho que alto, utilice android:gravity="fill_vertical". De lo contrario, use android:gravity="fill_horitzonal". Esto tiene un efecto similar al de usar android:scaleType="centerCrop" en un ImageView.

<bitmap xmlns:android="http://schemas.android.com/apk/res/android" 
    android:gravity="fill_vertical" 
    android:src="@drawable/image" /> 

Si admite múltiples orientaciones, puede crear un archivo de mapa de bits XML en la carpeta drawable-port y el otro en la carpeta drawable-land.

1

Quería hacer algo similar en mi clase Drawable personalizada. Estas son las piezas importantes:

public class CustomBackgroundDrawable extends Drawable 
{ 
    private Rect mTempRect = new Rect(); 
    private Paint mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 

    ... 

public void draw(@NonNull Canvas canvas) 
{ 
    Rect bounds = getBounds(); 
    if (mBitmap != null) { 
     if (mScaleType == ScaleType.SCALE_FILL) { 
      //bitmap scales to fill the whole bounds area (bitmap can be cropped) 
      if (bounds.height() > 0 && bounds.height() > 0) { 
       float scale = Math.min(mBitmap.getWidth()/(float)bounds.width(), mBitmap.getHeight()/(float)bounds.height()); 

       float bitmapVisibleWidth = scale * bounds.width(); 
       float bitmapVisibleHeight = scale * bounds.height(); 

       mTempRect.set((int)(mBitmap.getWidth()-bitmapVisibleWidth)/2, 0, (int)(bitmapVisibleWidth+mBitmap.getWidth())/2, (int)bitmapVisibleHeight); 
       canvas.drawBitmap(mBitmap, mTempRect, bounds, mBitmapPaint); 
      } 
     } else if (mScaleType == ScaleType.SCALE_FIT) { 
      //bitmap scales to fit in bounds area 
      if (bounds.height() > 0 && bounds.height() > 0) { 
       float scale = Math.min((float)bounds.width()/mBitmap.getWidth(), (float)bounds.height()/mBitmap.getHeight()); 

       float bitmapScaledWidth = scale * mBitmap.getWidth(); 
       float bitmapScaledHeight = scale * mBitmap.getHeight(); 
       int centerPadding = (int)(bounds.width()-bitmapScaledWidth)/2; 
       mTempRect.set(bounds.left + centerPadding, bounds.top, bounds.right - centerPadding, bounds.top+(int)bitmapScaledHeight); 
       canvas.drawBitmap(mBitmap, null, mTempRect, mBitmapPaint); 
      } 
     } 
    } 
} 

Con este enfoque es flexible para aplicar cualquier lógica de escala que necesita

Cuestiones relacionadas