Botón de Android con icono y texto

92

Tengo algunos botones como este en mi aplicación:

    <Button
        android:id="@+id/bSearch"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="Search"
        android:textSize="24sp" />

Estoy intentando crear un mismo botón con texto y un icono. android: drawableLeft no funciona para mí (tal vez lo haría, pero no sé cómo establecer una altura máxima para el icono).

Así que creé un LinearLayout con ImageView y TextView y lo hice actuar como un botón:

    <LinearLayout
        android:id="@+id/bSearch2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/btn_default"
        android:clickable="true"
        android:padding="16dp"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="5dp"
            android:adjustViewBounds="true"
            android:maxHeight="30dp"
            android:maxWidth="30dp"
            android:scaleType="fitCenter"
            android:src="@drawable/search_icon" />

        <TextView
            android:id="@+id/tvSearchCaption"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textSize="24sp"
            android:paddingRight="30dp"
            android:gravity="center"
            android:text="Search" />
    </LinearLayout>

Mi nuevo botón es exactamente lo que quiero (tamaño de fuente, icono y ubicación del texto). Pero no se parece a mis botones predeterminados:

ingrese la descripción de la imagen aquí

Así que intenté cambiar el fondo y el color del texto de mi nuevo botón:

Button Search = (Button) findViewById(R.id.bSearch);
LinearLayout bSearch2 = (LinearLayout) findViewById(R.id.bSearch2);
bSearch2.setBackground(bSearch.getBackground());
TextView tvSearchCaption = (TextView)findViewById(R.id.tvSearchCaption);
tvSearchCaption.setTextColor(bSearch.getTextColors().getDefaultColor());

Esto da un resultado extraño, mi viejo botón se estropea:

ingrese la descripción de la imagen aquí

Cuando cambio el orden de estos dos botones en el XML, por lo que el "botón nuevo" va primero, produce otro resultado extraño:

ingrese la descripción de la imagen aquí

Ahora me di cuenta de que cuando trato de presionar el botón antiguo, se presiona el nuevo.

¿Algunas ideas?

Dusan
fuente

Respuestas:

283

Prueba este.

<Button
    android:id="@+id/bSearch"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:text="Search"
    android:drawableLeft="@android:drawable/ic_menu_search"
    android:textSize="24sp"/>
Liem Vo
fuente
3
Eso se ve exactamente como lo quiero, pero quiero usar mis propios íconos, no los predeterminados de Android. Mis iconos son de mayor tamaño. ¿Eso significa que necesito crear mapas de bits más pequeños para cada resolución? ¿Existe algún parámetro que me permita controlar el tamaño del icono?
Dusan
Eso es correcto. Necesita crear un tamaño de imagen diferente para cada resolución
Liem Vo
Ok, gracias por tu ayuda, pero ahora tengo otra pregunta ... Mis íconos son claros, porque el texto es blanco en un botón oscuro, como puedes ver en las imágenes de mi pregunta. La aplicación está configurada para usar un tema que está disponible en la versión de Android. Mis ejemplos son de Android 4.3. Cuando la aplicación se ejecuta en Android 2.3.3, los botones predeterminados son claros con texto oscuro. Algo así como el botón de mi primera imagen. ¿Existe alguna forma de proporcionar un mapa de bits alternativo para el icono que se ejecuta en dispositivos más antiguos? Espero que entiendas mi pregunta :)
Dusan
Esa es una buena pregunta. Puede definir un estilo diferente para su icono, texto más fresco en estilo para cada nivel de API (significa versión del sistema operativo Android). Puede ver las carpetas values-v11, values-v14.
Liem Vo
2
También puede agregar relleno al icono de Android: drawablePadding = ""
Asad Mirza
15

Para agregar una imagen a la izquierda, derecha, arriba o abajo, puede usar atributos como este:

android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom

El código de muestra se da arriba. También puede lograr esto usando un diseño relativo.

usuario3515854
fuente
¿Cómo hago esto programáticamente
Sujay UN
1
Podría decir en android:drawableStartlugar de Izquierda y en android:drawableEndlugar de Derecha.
Simão García
@ SimãoGarcia * debería. El inicio debe reemplazar a la derecha y el final debe reemplazar a la izquierda en todos los lugares. Esto es para asegurar que la lectura de derecha a izquierda, así como la lectura de izquierda a derecha, esté disponible, ya que algunos otros países leen de manera diferente.
Carson J.
11

Para cualquiera que busque hacer esto dinámicamente, setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)el objeto de botones será de ayuda.

Muestra

Button search = (Button) findViewById(R.id.yoursearchbutton);
search.setCompoundDrawables('your_drawable',null,null,null);
Kennedy Nyaga
fuente
5
El uso de setCompoundDrawables no se reflejó en la interfaz de usuario. Se usó setCompoundDrawablesWithIntrinsicBounds en su lugar, y funcionó.
Aldo
5

Esto es lo que realmente quieres.

<Button
       android:id="@+id/settings"
       android:layout_width="190dp"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal"
       android:background="@color/colorAccent"
       android:drawableStart="@drawable/ic_settings_black_24dp"
       android:paddingStart="40dp"
       android:paddingEnd="40dp"
       android:text="settings"
       android:textColor="#FFF" />
Apilar
fuente
4

Puede utilizar la biblioteca de componentes de materiales y el MaterialButtoncomponente.
Utilice los atributos app:icony app:iconGravity="start".

Algo como:

  <com.google.android.material.button.MaterialButton
        style="@style/Widget.MaterialComponents.Button.Icon"
        app:icon="@drawable/..."
        app:iconGravity="start"
        ../>

ingrese la descripción de la imagen aquí

Gabriele Mariotti
fuente
Tenga en cuenta que si tiene un tema de diseño de materiales para su aplicación, el widget de botón estándar se infla automáticamente como MaterialButton. Por aquí - material.io/develop/android/components/buttons
dodgy_coder
2

La respuesta de @Liem Vo es correcta si está utilizando android.widget.Button sin ninguna anulación. Si está anulando su tema usando MaterialComponents, esto no resolverá el problema.

Entonces si tu eres

  1. Usando com.google.android.material.button.MaterialButton o
  2. Reemplazo de AppTheme usando MaterialComponents

Utilice la aplicación: parámetro de icono .

<Button
    android:id="@+id/bSearch"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:text="Search"
    android:textSize="24sp"
    app:icon="@android:drawable/ic_menu_search" />
Chamin Wickramarathna
fuente