Android: combiner texte et image sur un bouton ou un bouton d'image

540

J'essaie d'avoir une image (comme arrière-plan) sur un bouton et d'ajouter dynamiquement, en fonction de ce qui se passe pendant l'exécution, du texte au-dessus / au-dessus de l'image.

Si j'utilise, ImageButtonje n'ai même pas la possibilité d'ajouter du texte. Si j'utilise, Buttonje peux ajouter du texte mais uniquement définir une image avec android:drawableBottomdes attributs XML similaires tels que définis ici .

Cependant, ces attributs combinent uniquement le texte et l'image dans les dimensions x et y, ce qui signifie que je peux dessiner une image autour de mon texte, mais pas en dessous / sous mon texte (avec l'axe z défini comme sortant de l'affichage).

Des suggestions sur la façon de procéder? Une idée serait d'étendre Buttonou ImageButtonet de remplacer la draw()méthode -m. Mais avec mon niveau actuel de connaissances, je ne sais pas vraiment comment faire (rendu 2D). Peut-être que quelqu'un avec plus d'expérience connaît une solution ou au moins quelques conseils pour commencer?

znq
la source
utilisez 9Patch, une solution intelligente
Kaveh Garshasp
salut @Charu ක veuillez vérifier si vous pouvez stackoverflow.com/questions/42968587/…
Mohamed Rihan

Réponses:

205

Vous pouvez appeler setBackground()un Buttonpour définir l'arrière-plan du bouton.

Tout texte apparaîtra au-dessus de l'arrière-plan.

Si vous cherchez quelque chose de similaire en XML, il y a: android:backgroundattribut qui fonctionne de la même manière.

m_vitaly
la source
49
Si vous suivez cette voie, vous ne voulez pas simplement utiliser un simple dessinable pour l'arrière-plan. Utilisez un StateListDrawable (généralement via le fichier XML <selector> dans res / drawable /), afin de pouvoir définir des arrière-plans pour les différents états (normal, enfoncé, concentré, désactivé, etc.).
CommonsWare
D'accord avec vous, recherchez cette question et ma réponse: stackoverflow.com/questions/1533038/…
m_vitaly
1
Tellement stupide. Comment aurais-je pu manquer ça dans la documentation. Merci pour la réponse rapide et aussi l'astuce avec le <sélecteur>. C'est quelque chose que je veux définitivement mettre en œuvre à l'avenir.
znq
3
Cela ne fonctionne pas correctement sur les versions ICS 4.0+, l'image s'étire. J'utilisais un TextView avec un arrière-plan.
meh
612

Pour les utilisateurs qui souhaitent simplement mettre en arrière-plan, image-icône et texte dans un Button fichier différent: Buttondéfinissez sur un arrière - plan, des attributs drawableTop / Bottom / Rigth / Left et 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>

Pour un arrangement plus sophistiqué, vous pouvez également utiliser RelativeLayout(ou toute autre disposition) et le rendre cliquable.

Tutoriel: grand tutoriel qui couvre les deux cas: http://izvornikod.com/Blog/tabid/82/EntryId/8/Creating-Android-button-with-image-and-text-using-relative-layout.aspx

Un seul monde
la source
70
Pour ce faire, utilisez par programme à la b.setCompoundDrawablesWithIntrinsicBound(null,R.drawable.home_icon_test,null,null)place de android:drawableTopet b.setPadding(0,32,0,0)au lieu de android:paddingTop.
Alex Jasmin
3
L'utilisation d'une disposition comme bouton est en fait une approche assez flexible.
sstn
2
Remplacez simplement null par 0 si vous utilisez des identifiants de ressources pour vos drawables
Ran
1
Comment puis-je redimensionner l'image d'arrière-plan pour l'adapter au bouton?
Alston
@Stallman Il existe une solution basée sur xml et basée sur le code pour la mise à l'échelle: stackoverflow.com/questions/8223936/…
OneWorld
346

Il existe une bien meilleure solution à ce problème.

Prenez simplement une normale Buttonet utilisez drawableLeftles gravityattributs et.

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

De cette façon, vous obtenez un bouton qui affiche une icône dans le côté gauche du bouton et le texte à droite de l'icône centrée verticalement .

schlingel
la source
2
Un problème se produit avec cette solution si vous avez choisi d'avoir une couleur d'arrière-plan sur le bouton (ce qui est probable dans ce cas). Il n'y aura alors aucune réponse graphique au clic ou à la sélection. Vous pouvez écrire un sélecteur pour gérer cela, mais vous n'obtiendrez pas les couleurs par défaut du téléphone.
Vanja
9
Je voulais juste ajouter que la propriété de remplissage Drawable est très utile si cette solution est utilisée.
Nikola Malešević
5
Existe-t-il un moyen de définir la hauteur et la largeur d'une icône dessinable en XML?
penguru
18
C'est une excellente solution et est également officiellement approuvée sur le site des développeurs Android: developer.android.com/guide/topics/ui/controls/button.html
twaddington
3
si le bouton est grand et que le texte est long, cela ressemble à laid: icône tout à gauche et texte quelque part au milieu
67

entrez la description de l'image ici

     <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
la source
4
Une solution simple et erronée. Uniquement pour l'alignement à gauche.
CoolMind
2
@ CoolMind J'explique seulement pour l'image ci-dessus que j'ai jointe ..si vous voulez aligner à droite, utilisez drawableRight
Dhina k
Je ne pensais même pas à le faire avant d'avoir lu cette réponse. Ça fonctionne super bien!
sud007
59

Il suffit d'utiliser un LinearLayout et de faire comme si c'était un Buttonparamètre backgroundet cliquable est la clé:

<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
la source
1
Comment ajouter un effet cliqué?
franque
3
Meilleure réponse, de cette façon, vous gérez 100% de l'apparence et vous n'avez pas à coller l'icône sur une bordure.
Climbatize
français, ajoutez android:onClickà votre vue
Giora Guttsait
43

il suffit de remplacer

android:background="@drawable/icon"

avec

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

izz une assez bonne astuce ..;)

CMA
la source
21

J'ai adopté une approche différente de celles énoncées ici, et cela fonctionne très bien, j'ai donc voulu la partager.

J'utilise un style pour créer un bouton personnalisé avec l'image à gauche et le texte au centre à droite. Suivez simplement les 4 "étapes faciles" ci-dessous:

I. Créez vos 9 patchs en utilisant au moins 3 fichiers PNG différents et l'outil que vous avez sur: /YOUR_OWN_PATH/android-sdk-mac_x86/tools/./draw9patch. Après cela, vous devriez avoir:

button_normal.9.png, button_focused.9.png et button_pressed.9.png

Ensuite, téléchargez ou créez une icône PNG 24x24.

ic_your_icon.png

Enregistrez tout dans le dossier drawable / de votre projet Android.

II. Créez un fichier XML appelé button_selector.xml dans votre projet sous le dossier drawable /. Les états devraient être comme ceci:

<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. Accédez au dossier values ​​/ et ouvrez ou créez le fichier styles.xml et créez le code XML suivant:

<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 est un "style enfant" car il étend ButtonNormalText (le "style parent").

Notez que la modification de drawableLeft dans le style ButtonNormalTextWithIcon, en drawableRight, drawableTop ou drawableBottom vous pouvez placer l'icône dans une autre position par rapport au texte.

IV. Accédez à la mise en page / dossier où vous avez votre XML pour l'interface utilisateur et allez au bouton où vous souhaitez appliquer le style et le faire ressembler à ceci:

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

Et ... voilà! Vous avez obtenu votre bouton avec une image sur le côté gauche.

Pour moi, c'est la meilleure façon de le faire! car en procédant de cette façon, vous pouvez gérer la taille du texte du bouton séparément de l'icône que vous souhaitez afficher et utiliser le même arrière-plan que vous pouvez dessiner pour plusieurs boutons avec des icônes différentes en respectant les directives de l'interface utilisateur Android à l'aide de styles.

Vous pouvez également créer un thème pour votre application et y ajouter le "style parent" pour que tous les boutons se ressemblent et appliquer le "style enfant" avec l'icône uniquement là où vous en avez besoin.

Oscar Salguero
la source
Bon travail. J'utilisais une approche de vue FrameLayout avec une ImageView et une TextView à l'intérieur, mais cette approche est plus agréable.
pilcrowpipe
Super approche. Le SDK facebook (version 3) adopte la même approche pour le bouton de connexion
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
la source
11

Vous pouvez utiliser drawableTop(également drawableLeft, etc.) pour l'image et définir le texte sous l'image en ajoutant legravity 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
la source
11

Mise à jour importante

N'utilisez pas normal, android:drawableLeftetc ... avec des dessins vectoriels, sinon il se plantera dans les versions d'API inférieures . (Je l'ai fait face dans l'application en direct)

Pour vecteur dessinable

Si vous utilisez le dessin vectoriel, vous devez

  • Avez-vous migré vers AndroidX? sinon, vous devez d'abord migrer vers AndroidX. C'est très simple, voyez ce qu'est androidx, et comment migrer?
  • Il a été publié en version 1.1.0-alpha01, donc la version compatible avec l'app devrait être au moins 1.1.0-alpha01. La dernière version actuelle est 1.1.0-alpha02, utilisez les dernières versions pour une meilleure fiabilité, voir les notes de version - lien .

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

  • Utilisez AppCompatTextView/ AppCompatButton/AppCompatEditText

  • Utilisez app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompatetapp:drawableEndCompat

Pour étirer régulièrement

Si vous n'avez pas besoin de dessin vectoriel, vous pouvez

  • utilisation android:drawableLeft, android:drawableRight, android:drawableBottom,android:drawableTop
  • Vous pouvez utiliser des classes régulières TextViewet Button& EditTextou AppCompat.

Vous pouvez obtenir une sortie comme ci-dessous -

production

Khemraj
la source
J'utilise l' xmlns:app="http://schemas.android.com/apk/res-auto"espace de noms et je ne vois pas ces choses compatibles avec les applications.
Dale
1
@Dale votre espace de noms est correct, j'ai mis à jour ma réponse, voir à For vector drawablenouveau le point.
Khemraj
@Khemraj Comment vous centrez à la fois le dessin et le texte dans la vue unique (soit TextView ou Button ou autre) comme affiché dans l'image que vous avez jointe?
Ambar Jain
7

Ma solution conviendra probablement à beaucoup d'utilisateurs, je l'espère.

Ce que je suggère, c'est faire TextView avec votre style. Il fonctionne parfaitement pour moi et possède toutes les fonctionnalités, comme un bouton.

Tout d'abord, faisons un style de bouton, que vous pouvez utiliser partout ... Je crée 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>

Deuxièmement, permet de créer un bouton d'affichage de texte.

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

Et c'est un résultat. Stylisez ensuite votre bouton personnalisé avec n'importe quelle couleur ou toute autre propriété et marge. Bonne chance

entrez la description de l'image ici

Jevgenij Kononov
la source
Bien que je n'aie pas encore testé votre code, l'approche semble correcte, mais je ne comprends pas la raison d'avoir un effet de survol dans une application mobile.
Mohammed Akhtar Zuberi
J'ai créé un effet de survol pour mon application, et pendant cette génération d'application, j'avais besoin d'un effet de survol. Mais c'est à vous de choisir :) Vous pouvez supprimer l'effet de survol si ce n'est pas nécessaire.
Jevgenij Kononov
J'ai voté votre réponse car c'est une très bonne approche. Mon seul point est sur une interface mobile, comment pouvez-vous survoler?
Mohammed Akhtar Zuberi
Oo ... Je vois maintenant ..: D Yeap, tu as raison. C'est impossible. Cet effet de survol est principalement pour l'effet de pression. Nom juste incorrect pour la classe xml
Jevgenij Kononov
5

Ce code fonctionne parfaitement pour moi

<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
la source
J'ai essayé votre code .. il fonctionne mais le principal problème de votre code si vous avez défini des boutons, avec différentes tailles de texte dans chaque bouton. Votre mise en page sera décalée. Ainsi, chaque position d'image du bouton sera à un endroit différent. Alors qu'il devrait être droit au centre. C'est ce qui se passe avec le bouton.
Jevgenij Kononov
0

Vous pouvez utiliser ceci:

  <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 ce que j'ai mis une image backgroundet aussi ajouté du texte ..!

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

Ou vous pouvez par programme:

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
la source
-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
la source
Ce n'est pas une bonne réponse car la vue Image ne supporte pas le texte
Muhammed Fasil