¿Cómo implementar un Android: fondo que no se estira?

100

Encontré este gran hilo que describe cómo "comer el pastel y tenerlo también", es decir, usar la imagen en Buttonlugar de ImageButton(que no permite SetText(), cambiar el tamaño, etc.).

Esto se logra utilizando el atributo Ver:

android:background="@drawable/bgimage"

El único problema con esto es que estira la imagen para que se ajuste al tamaño del botón.

Aparte de codificar de forma rígida un tamaño de botón fijo (¡en píxeles!), ¿Hay alguna manera de decirle a Android que no estire la imagen de fondo en absoluto y que la recorte o la rellene?

ef2011
fuente

Respuestas:

29

Debe usar ImageView si no quiere que se estire. Las imágenes de fondo siempre se estirarán para adaptarse a la vista. Debe configurarlo como dibujable para forzar el aspecto de la imagen al objeto.

De lo contrario, si sigue con la idea del botón, deberá forzar la escala en el botón para evitar que la imagen se estire.

Código:

onCreate(Bundle bundle) {
  // Set content layout, etc up here

  // Now adjust button sizes
  Button b = (Button) findViewById(R.id.somebutton);
  int someDimension = 50; //50pixels
  b.setWidth(someDimension);
  b.setHeight(someDimension);
}
Dr.J
fuente
1
Gracias + 1. ImageViewparece interesante. Me di cuenta de que tiene un atributo que no está en Button: android:cropToPadding. No me importa usar un ImageView en su lugar, siempre que lo haya hecho setOnClickListener(), lo que hace. ¿Qué perderé al cambiar de Buttona ImageView?
ef2011
1
Por cierto, la segunda solución que sugirió aún estira la imagen.
ef2011
Terminé usando un tamaño de botón fijo (¡en píxeles!) Pero acepto su respuesta porque la primera sugerencia parece una solución alternativa de trabajo.
ef2011
1
@ ef2011 Para ImageView, no lo configure como una imagen de fondo, debe configurarlo como setDrawableResourcey luego asegurarse de que setAdjustViewBoundsesté configurado como verdadero
Dr.J
9
Voto en contra por una solución poco convincente. Solución correcta aquí: stackoverflow.com/a/9362168/145046
Aleks N.
260

Puede crear un mapa de bits xml y usarlo como fondo para la vista. Para evitar el estiramiento, puede especificar un android:gravityatributo.

por ejemplo:

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

Hay muchas opciones que puede utilizar para personalizar la representación de la imagen.

http://developer.android.com/guide/topics/resources/drawable-resource.html#Bitmap

Santosh
fuente
3
Usar ImageViews es una solución alternativa que no siempre es una opción posible; creo que esta es la solución adecuada :)
JakeP
3
Estoy configurando el fondo en tiempo de ejecución. ¿Existe alguna solución para crear mapas de bits en tiempo de ejecución?
Vivek Kumar Srivastava
1
para mí esta fue la mejor solución, pero eliminando el atributo "gravedad", lo que hace que coincida con su valor predeterminado "relleno". Esto permitirá cambiar el tamaño de la imagen para que se ajuste a la pantalla. Estudie el enlace de @Santosh para obtener más información. ¡Gracias!
Hugo
12
Solo veo un problema con este enfoque. Si la fuente dibujable ya es más grande que el contenedor, esto recortará la imagen (según la gravedad) en lugar de cambiar su tamaño, manteniendo la relación de aspecto, para que se ajuste al contenedor.
Shashwat Black
1
Ahora parece un poco anticuado. Esto solo funciona para mapas de bits y no para elementos de diseño vectoriales.
The_Sympathizer
25

Simplemente usar en ImageButtonlugar de Buttonsolucionar el problema.

<ImageButton android:layout_width="30dp"
             android:layout_height="30dp"
             android:src="@drawable/bgimage" />

y puedes configurar

android:background="@null"

para eliminar el fondo del botón si lo desea.

Arreglo rapido !! :-)

Adil Malik
fuente
1
Y luego establezca la imagen con el método setImageResource () ... que funcionó para mí.
arlomedia
quería tanto la imagen como el color de fondo en un botón ... esto funcionó como un encanto
Abhishek Chauhan
Funciona con más precisión para mí (quiero decir, "layout_centerVertical", por ejemplo).
Maxim Firsoff
11

Estoy usando un ImageView en un RelativeLayout que se superpone con mi diseño normal. No se requiere código. Ajusta el tamaño de la imagen a la altura completa de la pantalla (o cualquier otro diseño que use) y luego recorta la imagen hacia la izquierda y hacia la derecha para que se ajuste al ancho. En mi caso, si el usuario gira la pantalla, la imagen puede ser un poquito demasiado pequeña. Por lo tanto, uso match_parent, que hará que la imagen se estire en ancho si es demasiado pequeña.

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

    <ImageView
        android:id="@+id/main_backgroundImage"
        android:layout_width="match_parent"
        //comment: Stretches picture in the width if too small. Use "wrap_content" does not stretch, but leaves space

        android:layout_height="match_parent"
        //in my case I always want the height filled

        android:layout_alignParentTop="true"
        android:scaleType="centerCrop"
        //will crop picture left and right, so it fits in height and keeps aspect ratio

        android:contentDescription="@string/image"
        android:src="@drawable/your_image" />

    <LinearLayout
        android:id="@+id/main_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>
Gunnar Bernstein
fuente
En realidad, esta es una solución mucho más fácil para un problema que no debería existir
Ákos Nikházy
6

Tuve el mismo problema: solo debes usar una imagen de 9 parches (.9.png) en lugar de tu imagen original.

Sarga

Serge Bollaerts
fuente
5

Use draw9patch ... incluido dentro de las herramientas SDK de Android Studio. Puede definir las áreas extensibles de su imagen. Las partes importantes están restringidas y la imagen no parece del todo deformada. Una buena demostración de dra9patch está AQUÍ

Use draw9patch para cambiar su splash.png existente a new_splash.9.png, arrastre new_splash.9.png a la carpeta del proyecto drawable-hdpi y asegúrese de que AndroidManifest y styles.xml sean correctos como se muestra a continuación:

AndroidManifest.xml:

<application
...
        android:theme="@style/splashScreenStyle"
>

styles.xml:

<style name="splashScreenStyle" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowBackground">@drawable/new_splash</item>
</style>
WM1
fuente
3

Tenía una imagen de fondo, no de gran tamaño, pero con dimensiones extrañas, por lo tanto, el estiramiento y el mal rendimiento. Hice un método con los parámetros Contexto, una Vista y un ID dibujable (int) que coincidirá con el tamaño de la pantalla del dispositivo. Use esto, por ejemplo, en Fragments onCreateView para establecer el fondo.

public void setBackground(Context context, View view, int drawableId){
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),drawableId);

    bitmap = Bitmap.createScaledBitmap(bitmap, Resources.getSystem().
             getDisplayMetrics().widthPixels,
             Resources.getSystem().getDisplayMetrics().heightPixels,
             true);

    BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), 
                                    bitmap);

    view.setBackground(bitmapDrawable);
}
ZooMagic
fuente
1

Aquí hay una versión de la respuesta de Santosh para botones creados mediante programación, sin la necesidad de una configuración XML separada:

Button button = new Button(getContext());
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_button);
BitmapDrawable backgroundDrawable = new BitmapDrawable(getResources(), backgroundBitmap);
backgroundDrawable.setGravity(Gravity.CENTER); // also LEFT, CENTER_VERTICAL, etc.
backgroundDrawable.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP));
button.setBackground(backgroundDrawable);

Incluí la línea ColorFilter ya que funciona de manera un poco diferente a los botones con una imagen de fondo normal.

arlomedia
fuente
1

Puede usar a FrameLayoutcon a ImageViewcomo primer hijo, luego su diseño normal como segundo hijo:

<?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="match_parent">

  <ImageView
        android:id="@+id/background_image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/your_drawable"/>

  <LinearLayout
        android:id="@+id/your_actual_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

  </LinearLayout>

</FrameLayout>
Adam Johns
fuente
0

La clave es establecer el dibujable como la imagen del botón, no como fondo. Me gusta esto:

rb.setButtonDrawable(R.drawable.whatever_drawable);
José L Ugia
fuente
Este es un método de CompoundButton pero no de Button.
arlomedia
0

¿Se puede usar un ImageView simple en su xml y hacer que se pueda hacer clic (android: clickable = "true")? Solo tienes que usar como src una imagen que tenga la forma de un botón, es decir, esquinas redondeadas.

Grigoreas P.
fuente