2009-09-09 10 views
113

En un diseño, quiero escalar la imagen de fondo (manteniendo su relación de aspecto) al espacio asignado cuando se crea la página. Alguien tiene alguna idea de cómo hacer esto?Android: ¿Escala un Drawable o imagen de fondo?

Estoy usando layout.setBackgroundDrawable() y estoy usando BitmapDrawable para establecer Gravedad para el recorte y el relleno, pero no veo ninguna opción para escalar.

+0

Tuve este problema y seguí la recomendación de Dweebo con el cambio sugerido por Anke: cambiado fitXY para fitCenter. Funcionado bien. –

Respuesta

-4

usted tiene que pre-escala que estirable antes de usarla como fondo

+0

¿Es esta la única opción? ¿No hay ningún tipo de contenedor para colocar ImageView en el que pueda especificar el tamaño de visualización? – GrkEngineer

+0

cómo escalar previamente dibujable? –

+0

También estoy teniendo problemas con SurfaceView –

50

no hemos tratado de hacer exactamente lo que quiere, pero se puede escalar un ImageView usando android:scaleType="fitXY"
y será dimensionado para caber en cualquier tamaño que le des a ImageView.

Para que pueda crear un FrameLayout para su diseño, coloque el ImageView dentro de él, y luego cualquier otro contenido que necesite en el FrameLayout y con un fondo transparente.

<FrameLayout 
android:layout_width="fill_parent" android:layout_height="fill_parent"> 

    <ImageView 
android:layout_width="fill_parent" android:layout_height="fill_parent" 
android:src="@drawable/back" android:scaleType="fitXY" /> 

    <LinearLayout>your views</LinearLayout> 
</FrameLayout> 
+1

¿Es posible hacer esto en una superficie? De lo contrario, ¿Puedo mostrar la vista previa (para una aplicación de grabación) usando FrameLayout? – Namratha

+1

@dweebo: ¿Has probado esto? No parece estar funcionando para mí. – speedplane

+3

La bajada de valores desde el uso de dos componentes de la interfaz de usuario en lugar de uno es una mala idea, especialmente para componentes tan ocupados como ListView. Lo más probable es que tengas problemas mientras te desplazas. Solución adecuada: http://stackoverflow.com/a/9362168/145046 –

15

Para mantener la relación de aspecto que hay que utilizar o android:scaleType=fitCenterfitStart etc. Usando fitXY no mantendrá la relación de aspecto original de la imagen!

Tenga en cuenta que esto funciona solo para imágenes con un atributo src, no para la imagen de fondo.

80

Para personalizar la imagen de fondo de escala crear un recurso como este:

<?xml version="1.0" encoding="utf-8"?> 
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" 
    android:gravity="center" 
    android:src="@drawable/list_bkgnd" /> 

Entonces estará centrado en la vista si se utiliza como fondo. También hay otros indicadores: http://developer.android.com/guide/topics/resources/drawable-resource.html

+6

Intenté usar mapa de bits pero la imagen está simplemente centrada, no a escala, como pregunta Sam. Cuando uso ImageView, funciona muy bien, no hay problema. (n.b .: tampoco estoy desplazándome en mi caso.) ¿Con qué aumentaría el mapa de bits para escalar la imagen? –

+5

Los valores posibles son: "superior" | "abajo" | "izquierda" | "correcto" | "center_vertical" | "fill_vertical" | "center_horizontal" | "fill_horizontal" | "centro" | "llenar" | "clip_vertical" | "clip_horizontal" –

+14

ninguno de estos parámetros escala el mapa de bits, manteniendo su relación de aspecto, por lo que la respuesta es incorrecta. – Malachiasz

5

Cuando configura el Drawable de un ImageView utilizando el método setBackgroundDrawable, la imagen siempre se escalará. Se ignorarán los parámetros como adjustViewBounds o diferente ScaleTypes. La única solución para mantener la relación de aspecto que encontré es cambiar el tamaño del ImageView después de cargar el dibujante. Aquí está el fragmento de código utilicé:

// bmp is your Bitmap object 
int imgHeight = bmp.getHeight(); 
int imgWidth = bmp.getWidth(); 
int containerHeight = imageView.getHeight(); 
int containerWidth = imageView.getWidth(); 
boolean ch2cw = containerHeight > containerWidth; 
float h2w = (float) imgHeight/(float) imgWidth; 
float newContainerHeight, newContainerWidth; 

if (h2w > 1) { 
    // height is greater than width 
    if (ch2cw) { 
     newContainerWidth = (float) containerWidth; 
     newContainerHeight = newContainerWidth * h2w; 
    } else { 
     newContainerHeight = (float) containerHeight; 
     newContainerWidth = newContainerHeight/h2w; 
    } 
} else { 
    // width is greater than height 
    if (ch2cw) { 
     newContainerWidth = (float) containerWidth; 
     newContainerHeight = newContainerWidth/h2w; 
    } else { 
     newContainerWidth = (float) containerHeight; 
     newContainerHeight = newContainerWidth * h2w;  
    } 
} 
Bitmap copy = Bitmap.createScaledBitmap(bmp, (int) newContainerWidth, (int) newContainerHeight, false); 
imageView.setBackgroundDrawable(new BitmapDrawable(copy)); 
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 
imageView.setLayoutParams(params); 
imageView.setMaxHeight((int) newContainerHeight); 
imageView.setMaxWidth((int) newContainerWidth); 

En el fragmento de código anterior es bmp el objeto de mapa de bits que se va a mostrar y imageView es el ImageView objeto

Una cosa importante a destacar es el cambio de los parámetros de diseño. Esto es necesario porque setMaxHeight y setMaxWidth solo harán una diferencia si el ancho y el alto están definidos para envolver el contenido, no para llenar el elemento principal. Llenar los padres por el contrario es el ajuste deseado al principio, porque de lo contrario containerWidth y containerHeight a la vez tenga valores iguales a 0. Así, en su archivo de diseño va a tener algo como esto para su ImageView:

... 
<ImageView android:id="@+id/my_image_view" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"/> 
... 
2

Lo que Dweebo propuso funciona. Pero en mi humilde opinión, es innecesario. Un fondo dibuja escalas bien por sí mismo.La vista debería haber fijado la anchura y la altura, como en el siguiente ejemplo:

< RelativeLayout 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="@android:color/black"> 

    <LinearLayout 
     android:layout_width="500dip" 
     android:layout_height="450dip" 
     android:layout_centerInParent="true" 
     android:background="@drawable/my_drawable" 
     android:orientation="vertical" 
     android:padding="30dip" 
     > 
     ... 
    </LinearLayout> 
</RelativeLayout> 
+1

Según tengo entendido que un fondo se expandirá para llenar una vista, pero no se reducirá. –

0

Una opción es tratar de poner la imagen en la carpeta drawable-nodpi y poner el fondo de un diseño para el ID de recurso estirable.

Esto definitivamente funciona con la reducción de escala, aunque no he probado con la ampliación.

3

Ésta no es la solución mas potente, pero como alguien sugirió en lugar de fondo se puede crear FrameLayout o RelativeLayout y el uso ImageView como pseudo fondo - otros elementos serán posición simplemente por encima de ella:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent"> 

    <ImageView 
     android:id="@+id/ivBackground" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:scaleType="fitStart" 
     android:src="@drawable/menu_icon_exit" /> 

    <Button 
     android:id="@+id/bSomeButton" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="61dp" 
     android:layout_marginTop="122dp" 
     android:text="Button" /> 

</RelativeLayout> 

El problema con ImageView es que sólo scaleTypes disponibles son: CENTRO, CENTER_CROP, CENTER_INSIDE, FIT_CENTER, FIT_END, FIT_START, FIT_XY, MATRIZ (http://etcodehome.blogspot.de/2011/05/android-imageview-scaletype-samples.html)

y para "escalar la imagen de fondo (manteniendo su relación de aspecto)" en algún caso s, cuando quiere que una imagen ocupe toda la pantalla (por ejemplo, imagen de fondo) y la relación de aspecto de la pantalla es diferente a la de la imagen, el tipo de escala necesario es TOP_CROP, porque:

CENTER_CROP centra la imagen escalada en lugar de alineando el borde superior con el borde superior de la vista de la imagen y FIT_START se ajusta a la altura de la pantalla y no llena el ancho. Y como el usuario Anke notó que FIT_XY no mantiene la relación de aspecto.

mucho gusto que alguien ha extendido ImageView para apoyar TOP_CROP

public class ImageViewScaleTypeTopCrop extends ImageView { 
    public ImageViewScaleTypeTopCrop(Context context) { 
     super(context); 
     setup(); 
    } 

    public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setup(); 
    } 

    public ImageViewScaleTypeTopCrop(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     setup(); 
    } 

    private void setup() { 
     setScaleType(ScaleType.MATRIX); 
    } 

    @Override 
    protected boolean setFrame(int frameLeft, int frameTop, int frameRight, int frameBottom) { 

     float frameWidth = frameRight - frameLeft; 
     float frameHeight = frameBottom - frameTop; 

     if (getDrawable() != null) { 

      Matrix matrix = getImageMatrix(); 
      float scaleFactor, scaleFactorWidth, scaleFactorHeight; 

      scaleFactorWidth = (float) frameWidth/(float) getDrawable().getIntrinsicWidth(); 
      scaleFactorHeight = (float) frameHeight/(float) getDrawable().getIntrinsicHeight(); 

      if (scaleFactorHeight > scaleFactorWidth) { 
       scaleFactor = scaleFactorHeight; 
      } else { 
       scaleFactor = scaleFactorWidth; 
      } 

      matrix.setScale(scaleFactor, scaleFactor, 0, 0); 
      setImageMatrix(matrix); 
     } 

     return super.setFrame(frameLeft, frameTop, frameRight, frameBottom); 
    } 

} 

https://stackoverflow.com/a/14815588/2075875

Ahora mi humilde opinión sería perfecto si alguien escribió Disponibles a medida que escala la imagen de esa manera. Entonces podría usarse como parámetro de fondo.


Reflog sugiere preescalar dibujable antes de usarlo. Aquí está la instrucción de cómo hacerlo: Java (Android): How to scale a drawable without Bitmap? Aunque tiene una desventaja, ese mapa escalable/de mapa escalable utilizará más RAM, mientras que el escalado sobre la marcha utilizado por ImageView no requiere más memoria. La ventaja podría ser menos carga del procesador.

+0

¡Bonito!Hace exactamente lo que buscaba: imagen de fondo para llenar toda la pantalla aumentando el ancho proporcionalmente y recortando la parte inferior de la imagen. – CMash

2

El siguiente código hace que el mapa de bits se ajuste perfectamente al mismo tamaño de la imagen. Obtenga la altura y el ancho de la imagen de mapa de bits y luego calcule la nueva altura y ancho con la ayuda de los parámetros de la vista de imagen. Eso le da la imagen requerida con la mejor relación de aspecto.

int bwidth=bitMap1.getWidth(); 
int bheight=bitMap1.getHeight(); 
int swidth=imageView_location.getWidth(); 
int sheight=imageView_location.getHeight(); 
new_width=swidth; 
new_height = (int) Math.floor((double) bheight *((double) new_width/(double) bwidth)); 
Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap1,new_width,new_height, true); 
imageView_location.setImageBitmap(newbitMap) 
24

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 ganó No se muestra 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.

+1

Esta solución es definitivamente lo que estaba buscando desde hace mucho tiempo para reemplazar la propiedad de fondo de mi tema y evitar la escala de la imagen de manera diferente cuando la vista tiene pestañas o no. Gracias por compartir esto. – Bibu

7

Usar imagen como fondo dimensionado para el diseño:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" > 

    <ImageView 
     android:id="@+id/imgPlaylistItemBg" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:adjustViewBounds="true" 
     android:maxHeight="0dp" 
     android:scaleType="fitXY" 
     android:src="@drawable/img_dsh" /> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" > 


    </LinearLayout> 

</FrameLayout> 
+2

La respuesta real está aquí –

+0

¡Respuesta correcta, gracias! –

-4

Puede utilizar uno de los siguientes:

androide: gravedad = "fill_horizontal | clip_vertical"

O

androide: gravedad = "fill_vertical | clip_horizontal"

Cuestiones relacionadas