Android: combinando texto e imagem em um botão ou ImageButton


540

Estou tentando ter uma imagem (como plano de fundo) em um botão e adicionar dinamicamente, dependendo do que está acontecendo durante o tempo de execução, algum texto acima / acima da imagem.

Se eu usar ImageButton, nem tenho a possibilidade de adicionar texto. Se eu usarButton , posso adicionar texto, mas apenas definir uma imagem com android:drawableBottomatributos XML semelhantes e como definido aqui .

No entanto, esses atributos combinam apenas texto e imagem nas dimensões x e y, o que significa que posso desenhar uma imagem em torno do meu texto, mas não abaixo / abaixo do meu texto (com o eixo z definido como saindo da tela).

Alguma sugestão de como fazer isso? Uma idéia seria estender Buttonou ImageButtonsubstituir o draw()método. Mas com meu nível atual de conhecimento, eu realmente não sei como fazer isso (renderização em 2D). Talvez alguém com mais experiência saiba uma solução ou pelo menos alguns indicadores para começar?


use 9Patch, solução inteligente
Kaveh Garshasp

oi @Charu ක verifique isso se você pode stackoverflow.com/questions/42968587/...
Mohamed Rihan

Respostas:


205

Você pode chamar setBackground()a Buttonpara definir o plano de fundo do botão.

Qualquer texto aparecerá acima do plano de fundo.

Se você está procurando algo semelhante no xml, existe: android:backgroundattribute que funciona da mesma maneira.


49
Se você seguir esse caminho, não deseja usar apenas um desenho simples para o segundo plano. Use um StateListDrawable (geralmente via arquivo XML <selector> em res / drawable /), para definir planos de fundo para os vários estados (normal, pressionado, focado, desativado etc.).
CommonsWare 7/10/09

Concordo com você, procure esta pergunta e minha resposta: stackoverflow.com/questions/1533038/…
m_vitaly

1
Quão estúpido. Como eu poderia ter perdido isso na documentação. Obrigado pela resposta rápida e também pela dica com o <seletor>. Isso é algo que eu definitivamente quero implementar no futuro.
Znq 08/10/09

3
Não funciona bem nas versões do ICS 4.0+, a imagem se estende. Eu estava usando um TextView com um plano de fundo.
meh

612

Para usuários que querem apenas colocar o plano de fundo, imagem de ícone e texto em um Button de diferentes arquivos: em um Buttonplano de fundo, os atributos drawableTop / Bottom / Rigth / Left e padding .

<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 arranjos mais sofisticados, você também pode usar RelativeLayout(ou qualquer outro layout) e torná-lo clicável.

Tutorial: ótimo tutorial que abrange os dois casos: http://izvornikod.com/Blog/tabid/82/EntryId/8/Creating-Android-button-with-image-and-text-using-relative-layout.aspx


70
Para fazer isso, use programaticamente em b.setCompoundDrawablesWithIntrinsicBound(null,R.drawable.home_icon_test,null,null)vez de android:drawableTope em b.setPadding(0,32,0,0)vez de android:paddingTop.
Alex Jasmin

3
Usar um layout como botão é realmente uma abordagem bastante flexível.
sstn 27/05

2
Basta substituir nulo com 0 se você estiver usando IDs de recursos para seus drawables
Ran

1
Como dimensionar a imagem do fundo traseiro para caber no botão?
Alston

@Stallman Existe uma solução baseada em xml e baseada em código para dimensionamento: stackoverflow.com/questions/8223936/…
OneWorld

346

Existe uma solução muito melhor para esse problema.

Basta pegar um normal Buttone usar drawableLeftos gravityatributos

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

Dessa forma, você obtém um botão que exibe um ícone no lado esquerdo do botão e o texto no site direito do ícone centralizado na vertical .


2
Ocorre um problema com esta solução se você optar por ter uma cor de fundo no botão (o que provavelmente é o caso). Então não haverá resposta gráfica para clicar ou selecionar. Você pode escrever um seletor para lidar com isso, mas não obterá as cores padrão dos telefones.
Vanja

9
Só queria acrescentar que a propriedade Drawable padding é muito útil se essa solução for usada.
Nikola Malešević

5
Existe uma maneira de definir altura e largura para o ícone de desenho em xml?
Penguru

18
Esta é uma grande solução e também é endossado oficialmente no site do desenvolvedor Android: developer.android.com/guide/topics/ui/controls/button.html
twaddington

3
se o botão é grande eo texto é variável de comprimento, que se parece com feio: ícone, no máximo, à esquerda e em algum texto no meio

67

insira a descrição da imagem aqui

     <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" />

4
Uma solução simples e errada. Somente para alinhamento à esquerda.
CoolMind

2
@ CoolMind estou explicando apenas para imagem acima Anexei ..se quer uso align drawableRight direito
Dhina k

Eu nem estava pensando em fazer isso até ler esta resposta. Isso funciona como um encanto!
sud007 20/02

59

Basta usar um LinearLayout e fingir que é uma Button- configuração backgrounde clicável é a chave:

<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>

1
Como adicionar efeito clicado?
frankish

3
Melhor resposta: dessa maneira, você gerencia 100% da aparência e não precisa colar o ícone em uma borda.
Climbatize

frankish, adicione android:onClickà sua vista
Giora Guttsait

43

apenas substitua

android:background="@drawable/icon"

com

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

izz um truque muito bom ..;)


21

Eu adotei uma abordagem diferente da descrita aqui e está funcionando muito bem, então eu queria compartilhá-la.

Estou usando um estilo para criar um botão personalizado com imagem à esquerda e texto no centro-direita. Basta seguir os 4 "passos fáceis" abaixo:

I. Crie seus 9 patches usando pelo menos 3 arquivos PNG diferentes e a ferramenta que você possui em: /YOUR_OWN_PATH/android-sdk-mac_x86/tools/./draw9patch. Depois disso, você deve ter:

button_normal.9.png, button_focused.9.png e button_pressed.9.png

Em seguida, faça o download ou crie um ícone PNG 24x24.

ic_your_icon.png

Salve tudo na pasta drawable / no seu projeto Android.

II Crie um arquivo XML chamado button_selector.xml no seu projeto na pasta drawable /. Os estados devem ser assim:

<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 Vá para os valores / pasta e abra ou crie o arquivo styles.xml e crie o seguinte 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 é um "estilo filho" porque está estendendo o ButtonNormalText (o "estilo pai").

Observe que, alterando o drawableLeft no estilo ButtonNormalTextWithIcon, para drawableRight, drawableTop ou drawableBottom, você pode colocar o ícone em outra posição em relação ao texto.

IV Vá para o layout / pasta em que você possui seu XML para a interface do usuário e vá para o botão em que deseja aplicar o estilo e faça com que fique assim:

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

E ... voilà! Você conseguiu o seu botão com uma imagem no lado esquerdo.

Para mim, esta é a melhor maneira de fazê-lo! porque dessa maneira, você pode gerenciar o tamanho do texto do botão separadamente do ícone que deseja exibir e usar o mesmo plano de fundo desenhável para vários botões com ícones diferentes, respeitando as Diretrizes da interface do usuário do Android usando estilos.

Você também pode criar um tema para o seu aplicativo e adicionar o "estilo pai" a ele, para que todos os botões tenham a mesma aparência e aplicar o "estilo filho" com o ícone somente onde for necessário.


Bom trabalho. Eu estava usando uma abordagem de exibição FrameLayout com um ImageView e TextView dentro, mas essa abordagem é melhor.
pilcrowpipe

Abordagem impressionante. O SDK do Facebook (versão 3) segue a mesma abordagem para o botão de login
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"         
        />   

11

Você pode usar drawableTop(também drawableLeftetc) para a imagem e definir o texto abaixo da imagem adicionando ogravity 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" />

11

Atualização Importante

Não use normal android:drawableLeftetc ... com drawables vetoriais, senão ele trava nas versões mais baixas da API . (Eu já enfrentei isso no aplicativo ao vivo)

Para vetor desenhável

Se você estiver usando um vetor desenhável, deverá

  • Você migrou para o AndroidX? Caso contrário, você deve migrar para o AndroidX primeiro. É muito simples, veja o que é o androidx e como migrar?
  • Foi lançado na versão 1.1.0-alpha01, portanto a versão appcompat deve ser pelo menos 1.1.0-alpha01. A versão mais recente atual é 1.1.0-alpha02, use as versões mais recentes para melhor confiabilidade, consulte as notas de versão - link .

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

  • Use AppCompatTextView/ AppCompatButton/AppCompatEditText

  • Use app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompateapp:drawableEndCompat

Para drawable regular

Se você não precisar de um desenho vetorial, poderá

  • uso android:drawableLeft, android:drawableRight, android:drawableBottom,android:drawableTop
  • Você pode usar aulas regulares TextView, Button& EditTextou AppCompat.

Você pode obter resultados como abaixo -

resultado


Estou usando o xmlns:app="http://schemas.android.com/apk/res-auto"namespace e não vejo essas coisas compatíveis com aplicativos.
Dale

1
@ Dale seu espaço para nome está correto, atualizei minha resposta, consulte o For vector drawableponto novamente.
Khemraj

@Khemraj Como você centraliza o desenho e o texto na exibição única (um TextView ou Button ou outra coisa), conforme exibido na imagem anexada?
Ambar Jain

7

Provavelmente minha solução servirá para muitos usuários, espero que sim.

O que estou sugerindo é criar o TextView com seu estilo. Funciona perfeitamente para mim e possui todos os recursos, como um botão.

Antes de tudo, vamos criar o estilo do botão, que você pode usar em qualquer lugar ... Estou criando o 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>

Em segundo lugar, vamos criar um botão de exibição 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" />

E isso é resultado. Em seguida, estilize seu botão personalizado com todas as cores ou outras propriedades e margens. Boa sorte

insira a descrição da imagem aqui


Embora eu ainda precise testar seu código, a abordagem parece estar correta, mas não entendo o motivo de ter efeito de foco em um aplicativo móvel.
Mohammed Akhtar Zuberi

Criei efeito de foco para o meu aplicativo e, durante a criação do aplicativo, eu precisei de efeito de foco. Mas depende de você :) Você pode excluir o efeito de foco, se não for necessário.
Jevgenij Kononov 30/01

Votei sua resposta, pois é uma abordagem muito boa. Meu único ponto é em uma interface móvel, como você pode pairar?
Mohammed Akhtar Zuberi

Oo ... eu vejo agora ..: D Sim, você está certo. É impossível. Esse efeito de foco é principalmente para pressionar o efeito. Apenas nome incorreto para a classe xml
Jevgenij Kononov


5

Este código funciona para mim perfeitamente

<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>

Eu tentei o seu código .. ele funciona, mas o principal problema do seu código se você tiver um conjunto de botões, com tamanhos de texto diferentes em cada botão. Seu layout será alterado. Portanto, cada posição da imagem do botão estará em um local diferente. Embora deva ser reto no centro. É o que acontece com o botão.
Jevgenij Kononov 24/02

0

Você pode usar isto:

  <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" />

em que eu coloquei uma imagem como backgrounde também adicionei texto ..!


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

Ou você pode programaticamente:

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

-4
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/temp"
        />

Esta não é uma resposta certa porque o texto vista Imagem doesnt suppport
Muhammed Fasil
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.