Android: combina texto e imagen en un botón o ImageButton

540

Estoy tratando de tener una imagen (como fondo) en un botón y agregar dinámicamente, dependiendo de lo que ocurra durante el tiempo de ejecución, algo de texto sobre / sobre la imagen.

Si lo uso ImageButton, ni siquiera tengo la posibilidad de agregar texto. Si lo uso Button, puedo agregar texto pero solo definir una imagen con android:drawableBottomatributos XML similares a los definidos aquí .

Sin embargo, estos atributos solo combinan texto e imagen en dimensiones x e y, lo que significa que puedo dibujar una imagen alrededor de mi texto, pero no debajo / debajo de mi texto (con el eje z definido como saliendo de la pantalla).

¿Alguna sugerencia sobre cómo hacer esto? Una idea sería extender Buttono ImageButtonanular el draw()método-. Pero con mi nivel actual de conocimiento, realmente no sé cómo hacer esto (renderizado 2D). ¿Quizás alguien con más experiencia conoce una solución o al menos algunos consejos para comenzar?

znq
fuente
use 9Patch, solución inteligente
Kaveh Garshasp
hola @Charu ක, comprueba esto si puedes stackoverflow.com/questions/42968587/…
Mohamed Rihan

Respuestas:

205

Puede llamar setBackground()a a Buttonpara establecer el fondo del botón.

Cualquier texto aparecerá sobre el fondo.

Si está buscando algo similar en xml hay: android:backgroundatributo que funciona de la misma manera.

m_vitaly
fuente
49
Si sigue esta ruta, no desea utilizar un simple dibujo para el fondo. Utilice un StateListDrawable (generalmente a través del archivo XML <selector> en res / drawable /), para que pueda definir fondos para los diversos estados (normal, presionado, enfocado, deshabilitado, etc.).
CommonsWare
De acuerdo con usted, busque esta pregunta y mi respuesta: stackoverflow.com/questions/1533038/…
m_vitaly
1
Que estúpido. ¿Cómo podría haberme perdido eso en la documentación? Gracias por la respuesta rápida y también la pista con el <selector>. Eso es algo que definitivamente quiero implementar en el futuro.
znq
3
No funciona correctamente en las versiones ICS 4.0+, la imagen se extiende. Estaba usando un TextView con un fondo.
meh
612

Para los usuarios que solo desean poner Fondo, Imagen de icono y Texto en uno Button de diferentes archivos: Establecer en un Buttonfondo, dibujable Superior / Inferior / Derecho / Izquierdo y atributos de relleno .

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/home_btn_test"
        android:drawableTop="@drawable/home_icon_test"
        android:textColor="#FFFFFF"
        android:id="@+id/ButtonTest"
        android:paddingTop="32sp"
        android:drawablePadding="-15sp"
        android:text="this is text"></Button>

Para un arreglo más sofisticado, también puede usar RelativeLayout(o cualquier otro diseño) y hacer clic en él.

Tutorial: Gran tutorial que cubre ambos casos: http://izvornikod.com/Blog/tabid/82/EntryId/8/Creating-Android-button-with-image-and-text-using-relative-layout.aspx

Un mundo
fuente
70
Para hacer esto, use programáticamente en b.setCompoundDrawablesWithIntrinsicBound(null,R.drawable.home_icon_test,null,null)lugar de android:drawableTopy en b.setPadding(0,32,0,0)lugar de android:paddingTop.
Alex Jasmin
3
Usar un diseño como botón es en realidad un enfoque bastante flexible.
sstn
2
Simplemente reemplace nulo con 0 si está utilizando identificadores de recursos para sus objetos extraíbles
Ran
1
¿Cómo puedo escalar la imagen de fondo para que se ajuste al botón?
Alston
@Stallman Hay una solución basada en xml y en código para escalar: stackoverflow.com/questions/8223936/…
OneWorld
346

Hay una solución mucho mejor para este problema.

Simplemente tome una normalidad Buttony use drawableLeftlos gravityatributos y.

<Button
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:drawableLeft="@drawable/my_btn_icon"
  android:gravity="left|center_vertical" />

De esta forma, obtienes un botón que muestra un icono en el lado izquierdo del botón y el texto en el sitio derecho del icono centrado verticalmente .

Schlingel
fuente
2
Se produce un problema con esta solución si elige tener un color de fondo en el botón (que es probable en este caso). Entonces no habrá respuesta gráfica al clic o selección. Puede escribir un selector para manejar esto, pero no obtendrá los colores predeterminados del teléfono.
Vanja
99
Solo quería agregar que la propiedad de relleno Drawable es muy útil si se usa esta solución.
Nikola Malešević
55
¿Hay alguna manera de establecer la altura y el ancho del icono dibujable en xml?
penguru
18
Esta es una gran solución y también está oficialmente respaldada en el sitio para desarrolladores de Android: developer.android.com/guide/topics/ui/controls/button.html
twaddington
3
si el botón es grande y el texto es largo variable, entonces parece feo: icono en la parte superior izquierda y texto en algún lugar en el medio
67

ingrese la descripción de la imagen aquí

     <Button
            android:layout_width="0dp"
            android:layout_weight="1"
            android:background="@drawable/home_button"
            android:drawableLeft="@android:drawable/ic_menu_edit"
            android:drawablePadding="6dp"
            android:gravity="left|center"
            android:height="60dp"
            android:padding="6dp"
            android:text="AndroidDhina"
            android:textColor="#000"
            android:textStyle="bold" />
Dhina k
fuente
44
Una solución simple e incorrecta. Solo para alinear a la izquierda.
CoolMind
2
@ CoolMind Estoy explicando solo la imagen de arriba que he adjuntado ... si desea alinear correctamente use
drawableRight
Ni siquiera estaba pensando en hacer esto hasta que leí esta respuesta. Esto funciona como un encanto!
sud007
59

Solo use un LinearLayout y pretenda que es una Buttonconfiguración : la clave es hacer clicbackground y hacer clic

<LinearLayout
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:drawable/btn_default"
    android:clickable="true"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="5dp"
        android:src="@drawable/image" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_margin="5dp"
        android:text="Do stuff" />
</LinearLayout>
Kieran
fuente
1
¿Cómo agregar un efecto cliqueado?
franco
3
La mejor respuesta, de esta manera, administras el 100% de la apariencia y no tienes que pegar el ícono en un borde.
Climbatize
franco, añadir android:onClicka su punto de vista
Giora Guttsait
43

solo reemplace

android:background="@drawable/icon"

con

android:background="@android:color/transparent"
android:drawableTop="@drawable/[your background image here]"

izz un muy buen truco ..;)

CMA
fuente
21

Tomé un enfoque diferente de los que se indican aquí, y está funcionando muy bien, así que quería compartirlo.

Estoy usando un estilo para crear un botón personalizado con imagen a la izquierda y texto en el centro-derecha. Simplemente siga los 4 "pasos fáciles" a continuación:

I. Cree sus 9 parches usando al menos 3 archivos PNG diferentes y la herramienta que tiene en: /YOUR_OWN_PATH/android-sdk-mac_x86/tools/./draw9patch. Después de esto deberías tener:

button_normal.9.png, button_focused.9.png y button_pressed.9.png

Luego, descargue o cree un icono PNG 24x24.

ic_your_icon.png

Guarde todo en la carpeta dibujable / en su proyecto de Android.

II Cree un archivo XML llamado button_selector.xml en su proyecto en la carpeta / dibujable. Los estados deberían ser así:

<item android:state_pressed="true" android:drawable="@drawable/button_pressed" />
<item android:state_focused="true" android:drawable="@drawable/button_focused" />
<item android:drawable="@drawable/button_normal" />

III. Vaya a la carpeta valores / y abra o cree el archivo styles.xml y cree el siguiente código XML:

<style name="ButtonNormalText" parent="@android:style/Widget.Button">
    <item name="android:textColor" >@color/black</item>
    <item name="android:textSize" >12dip</item>
    <item name="android:textStyle" >bold</item>
    <item name="android:height" >44dip</item>
    <item name="android:background" >@drawable/button_selector</item>
    <item name="android:focusable" >true</item>
    <item name="android:clickable" >true</item>
</style>

<style name="ButtonNormalTextWithIcon" parent="ButtonNormalText">
    <item name="android:drawableLeft" >@drawable/ic_your_icon</item>
</style>

ButtonNormalTextWithIcon es un "estilo secundario" porque está extendiendo ButtonNormalText (el "estilo principal").

Tenga en cuenta que al cambiar drawableLeft en el estilo ButtonNormalTextWithIcon a drawableRight, drawableTop o drawableBottom, puede colocar el icono en otra posición con respecto al texto.

IV. Vaya al diseño / carpeta donde tiene su XML para la interfaz de usuario y vaya al botón donde desea aplicar el estilo y haga que se vea así:

<Button android:id="@+id/buttonSubmit" 
android:text="@string/button_submit" 
android:layout_width="fill_parent" 
android:layout_height="wrap_content" 
style="@style/ButtonNormalTextWithIcon" ></Button>

¡Y voilá! Tienes tu botón con una imagen en el lado izquierdo.

¡Para mí, esta es la mejor manera de hacerlo! porque al hacerlo de esta manera, puede administrar el tamaño del texto del botón por separado del icono que desea mostrar y usar el mismo fondo dibujable para varios botones con diferentes iconos respetando las Directrices de la interfaz de usuario de Android usando estilos.

También puede crear un tema para su aplicación y agregarle el "estilo principal" para que todos los botones se vean iguales, y aplicar el "estilo secundario" con el ícono solo donde lo necesite.

Oscar Salguero
fuente
Buen trabajo. Estaba usando un enfoque de vista FrameLayout con un ImageView y TextView dentro, pero este enfoque es mejor.
Pilcrowpipe
Enfoque impresionante. El SDK de Facebook (versión 3) adopta el mismo enfoque para el botón de inicio de sesión
Someone Somewhere
12
 <Button android:id="@+id/imeageTextBtn" 
        android:layout_width="240dip"
        android:layout_height="wrap_content"
        android:text="Side Icon With Text Button"
        android:textSize="20sp"
        android:drawableLeft="@drawable/left_side_icon"         
        />   
Salman Khursheed Khaleeqi
fuente
11

Puede usar drawableTop(también drawableLeft, etc.) para la imagen y establecer el texto debajo de la imagen agregando elgravity left|center_vertical

<Button
            android:id="@+id/btn_video"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@null"
            android:drawableTop="@drawable/videos"
            android:gravity="left|center_vertical"
            android:onClick="onClickFragment"
            android:text="Videos"
            android:textColor="@color/white" />
Kalai.G
fuente
11

Actualización importante

No use normal, android:drawableLeftetc ... con dibujos vectoriales, de lo contrario se bloqueará en versiones de API inferiores . (Lo he enfrentado en la aplicación en vivo)

Para vector dibujable

Si está utilizando vectores dibujables, entonces debe

  • ¿Has migrado a AndroidX? si no, primero debe migrar a AndroidX. Es muy simple, ¿ ves qué es androidx y cómo migrar?
  • Fue lanzado en versión 1.1.0-alpha01, por lo que la versión de appcompat debería ser al menos 1.1.0-alpha01. La última versión actual es 1.1.0-alpha02, use las últimas versiones para una mejor confiabilidad, vea las notas de la versión - enlace .

    implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'

  • Usar AppCompatTextView/ AppCompatButton/AppCompatEditText

  • Uso app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompatyapp:drawableEndCompat

Para dibujable regular

Si no necesita un vector dibujable, entonces puede

  • uso android:drawableLeft, android:drawableRight, android:drawableBottom,android:drawableTop
  • Puede utilizar cualquiera regulares TextView, Buttony EditTexto AppCompatclases.

Puede lograr la salida como a continuación:

salida

Khemraj
fuente
Estoy usando el xmlns:app="http://schemas.android.com/apk/res-auto"espacio de nombres y no veo esas cosas compatibles con la aplicación.
Dale
1
@Dale su espacio de nombres es correcto, he actualizado mi respuesta, vea el For vector drawablepunto nuevamente.
Khemraj
@Khemraj ¿Cómo está centrando tanto el dibujo como el texto en la vista única (ya sea TextView o Button u otra cosa) como se muestra en la imagen que adjuntó?
Ambar Jain
7

Probablemente mi solución se adapte a muchos usuarios, eso espero.

Lo que estoy sugiriendo es hacer TextView con tu estilo. Me funciona perfectamente y tiene todas las funciones, como un botón.

En primer lugar, hagamos un estilo de botón, que puede usar en todas partes ... Estoy creando button_with_hover.xml

    <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" >
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="#8dbab3" />
            <gradient android:angle="-90" android:startColor="#48608F" android:endColor="#48608F"  />
        </shape>

        <!--#284682;-->
        <!--border-color: #223b6f;-->
    </item>
    <item android:state_focused="true">
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="#284682" />
            <solid android:color="#284682"/>
        </shape>
    </item>
    <item >
        <shape android:shape="rectangle"  >
            <corners android:radius="3dip" />
            <stroke android:width="1dip" android:color="@color/ControlColors" />
            <gradient android:angle="-90" android:startColor="@color/ControlColors" android:endColor="@color/ControlColors" />
        </shape>
    </item>

</selector>

En segundo lugar, vamos a crear un botón de vista de texto.

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dip"
    android:layout_gravity="right|bottom"
    android:gravity="center"
    android:padding="12dip"
    android:background="@drawable/button_with_hover"
    android:clickable="true"
    android:drawableLeft="@android:drawable/btn_star_big_off"
    android:textColor="#ffffffff"
    android:text="Golden Gate" />

Y este es un resultado. Luego, diseñe su botón personalizado con cualquier color u otras propiedades y márgenes. Buena suerte

ingrese la descripción de la imagen aquí

Jevgenij Kononov
fuente
Aunque todavía no he probado su código, el enfoque parece ser correcto, pero no entiendo la razón de tener efecto de desplazamiento en una aplicación móvil.
Mohammed Akhtar Zuberi
He creado un efecto de desplazamiento para mi aplicación, y durante la creación de la aplicación necesitaba el efecto de desplazamiento. Pero depende de usted :) Puede eliminar el efecto de desplazamiento si no es necesario.
Jevgenij Kononov
He votado su respuesta, ya que es un muy buen enfoque. Mi único punto es en una interfaz móvil, ¿cómo puedes pasar el mouse?
Mohammed Akhtar Zuberi
Oo ... ahora veo ...: D Yeap, tienes razón. Es imposible. Ese efecto de desplazamiento es principalmente para presionar el efecto. Solo nombre incorrecto para la clase xml
Jevgenij Kononov
5

Este código me funciona perfectamente

<LinearLayout
    android:id="@+id/choosePhotosView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="center"
    android:clickable="true"
    android:background="@drawable/transparent_button_bg_rev_selector">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/choose_photo"/>

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:text="@string/choose_photos_tv"/>

</LinearLayout>
eyal
fuente
He probado su código ... funciona, pero el problema principal de su código es si tiene un conjunto de botones, con diferentes tamaños de texto en cada botón. Su diseño será cambiado. Por lo tanto, cada posición de la imagen del botón estará en un lugar diferente. Si bien debe ser recto en el centro. Esto es lo que sucede con el botón.
Jevgenij Kononov
0

Puedes usar esto:

  <Button
                    android:id="@+id/reset_all"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="5dp"
                    android:layout_weight="1"
                    android:background="@drawable/btn_med"
                    android:text="Reset all"
                    android:textColor="#ffffff" />

                <Button
                    android:id="@+id/undo"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="5dp"
                    android:layout_weight="1"
                    android:background="@drawable/btn_med"
                    android:text="Undo"
                    android:textColor="#ffffff" />

en el que he puesto una imagen backgroundy también he añadido texto ..!

jigar
fuente
0
<Button android:id="@+id/myButton" 
    android:layout_width="150dp"
    android:layout_height="wrap_content"
    android:text="Image Button"
    android:drawableTop="@drawable/myimage"         
    />  

O puedes programáticamente:

Drawable drawable = getResources.getDrawable(R.drawable.myimage);
drawable.setBounds(0, 0, 60, 60);
myButton.setCompoundDrawables(null, drawable, null, null);//to the Top of the Button
Kerim FIRAT
fuente
-4
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/temp"
        />
Jayesh Prajapati
fuente
Esta no es una respuesta correcta porque la vista de imagen no admite texto
Muhammed Fasil