Comment centrer l'icône et le texte dans un bouton Android dont la largeur est définie sur "Remplir le parent"


118

Je veux avoir un bouton Android avec l'icône + le texte centré à l'intérieur. J'utilise l'attribut drawableLeft pour définir l'image, cela fonctionne bien si le bouton a une largeur de "wrap_content"mais j'ai besoin de l'étirer à la largeur maximale, donc j'utilise la largeur "fill_parent". Cela déplace mon icône directement à gauche du bouton et je veux que l'icône et le texte soient centrés à l'intérieur du bouton.

J'ai essayé de configurer le rembourrage mais cela ne permet que de donner une valeur fixe, donc ce n'est pas ce dont j'ai besoin. J'ai besoin d'aligner l'icône + le texte au centre.

<Button 
    android:id="@+id/startTelemoteButton" 
    android:text="@string/start_telemote"
    android:drawableLeft="@drawable/start"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"            
    android:width="fill_parent"
    android:heigh="wrap_content" />

Des suggestions sur la façon dont je pourrais y parvenir?


Il est possible qu'il n'y ait pas de solution facile pour cela? Dois-je essayer avec un bouton 9patch img avec l'icône là-dedans?
jloriente

Cela pourrait être une solution. Le texte du bouton va-t-il être localisé ou statique?
Octavian A. Damiean

C'est localisé. Il n'y a pas d'autre solution pour cela? J'ai réussi à le faire avec un patch 9 mais ayant des problèmes lors du changement de locale.
jloriente

Pourquoi ne pas utiliser un bouton avec TOP dessinable et y ajouter un peu de rembourrage?
Francesco

bad framework design
Muhammad Babar

Réponses:


75

android: drawableLeft garde toujours android: paddingLeft comme distance de la bordure gauche. Lorsque le bouton n'est pas défini sur android: width = "wrap_content", il sera toujours suspendu à gauche!

Avec Android 4.0 (niveau d'API 14), vous pouvez utiliser l' attribut android: drawableStart pour placer un dessinable au début du texte. La seule solution rétrocompatible que j'ai proposée consiste à utiliser un ImageSpan pour créer un texte + image spannable:

Button button = (Button) findViewById(R.id.button);
Spannable buttonLabel = new SpannableString(" Button Text");
buttonLabel.setSpan(new ImageSpan(getApplicationContext(), R.drawable.icon,      
    ImageSpan.ALIGN_BOTTOM), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
button.setText(buttonLabel);

Dans mon cas, j'avais également besoin d'ajuster l'attribut android: gravity du Button pour le faire paraître centré:

<Button
  android:id="@+id/button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:minHeight="32dp"
  android:minWidth="150dp"
  android:gravity="center_horizontal|top" />

Agréable. La dernière ligne devrait êtrebutton.setText(buttonLabel)
AlexD

1
Unicode dispose d'un ensemble complet d'icônes de caractères compatibles avec les chaînes d'Android. Si vous pouvez en trouver une acceptable, c'est une solution simple, et elle a l'avantage supplémentaire de s'adapter à la taille du texte. Par exemple, il a une enveloppe pour une icône de courrier électronique et quelques téléphones différents pour un bouton d'appel.
GLee

1
Je ne comprends pas comment cela a fonctionné pour n'importe qui, pour moi, cela dessine 2 icônes ... un chemin vers la gauche et une directement au centre qui s'affiche en haut du texte.
Justin le

11
drawableStart ne fonctionnera pas. Voir ce fil: stackoverflow.com/questions/15350990/... Aussi, il semble que lorsque vous définissez le texte en utilisant un spannable, le style est ignoré.
Dapp

11
drawableStart ne fonctionne pas, et il a été ajouté au niveau de l'API 17 pour prendre en charge rtl
Silvia H

35

Je sais que je suis en retard pour répondre à cette question, mais cela m'a aidé:

<FrameLayout
            android:layout_width="match_parent"
            android:layout_height="35dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:background="@color/fb" >

            <Button
                android:id="@+id/fbLogin"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:background="@null"
                android:drawableLeft="@drawable/ic_facebook"
                android:gravity="center"
                android:minHeight="0dp"
                android:minWidth="0dp"
                android:text="FACEBOOK"
                android:textColor="@android:color/white" />
        </FrameLayout>

J'ai trouvé cette solution à partir d'ici: les difficultés de l'interface utilisateur Android: créer un bouton avec un texte et une icône centrés

entrez la description de l'image ici


6
Le problème avec ceci est que le bouton n'a pas la largeur de la disposition du cadre.
Clive Jefferies

29

J'ai utilisé LinearLayout au lieu de Button . Le OnClickListener , que je dois utiliser fonctionne très bien aussi pour LinearLayout.

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

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/icon" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Text" />

</LinearLayout>

29

Toutes les réponses précédentes semblent obsolètes

Vous pouvez utiliser le MaterialButtonmaintenant qui permet de régler la gravité de l'icône.

 <com.google.android.material.button.MaterialButton
        android:id="@+id/btnDownloadPdf"
        android:layout_width="0dp"
        android:layout_height="56dp"
        android:layout_margin="16dp"
        android:gravity="center"
        android:textAllCaps="true"
        app:backgroundTint="#fc0"
        app:icon="@drawable/ic_pdf"
        app:iconGravity="textStart"
        app:iconPadding="10dp"
        app:iconTint="#f00"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text="Download Pdf" />

entrez la description de l'image ici

Pour utiliser les composants matériels, vous devrez évidemment:

Ajouter une dépendance implementation 'com.google.android.material:material:1.3.0-alpha01' (utiliser la dernière version)

Faites étendre votre thème au thème Composants matériels

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>

Si vous ne pouvez pas le faire, étendez-le à partir du thème Material Bridge

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>

Merci! Tu as sauvé ma journée! Fonctionne bien
Black_Zerg

9

Je l'ajuste en ajoutant un rembourrage à gauche et à droite comme suit:

<Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/btn_facebookact_like"
            android:text="@string/btn_facebookact_like"
            android:textColor="@color/black"
            android:textAllCaps="false"
            android:background="@color/white"
            android:drawableStart="@drawable/like"
            android:drawableLeft="@drawable/like"
            android:gravity="center"
            android:layout_gravity="center"
            android:paddingLeft="40dp"
            android:paddingRight="40dp"
            />

Le paddingLeft et le paddingRight m'ont aidé dans mon centrage. voter pour une solution facile.
Arrie

2
Comment gérez-vous le fait que votre largeur soit dynamique? Si vous faites pivoter votre écran, toutes vos icônes ne seront pas centrées correctement? Je suis confronté à ce problème en fait
Jacks

C'est la meilleure réponse!
Dody Rachmat Wicaksono le

8

J'ai récemment rencontré le même problème. J'ai essayé de trouver une solution moins chère, alors j'ai trouvé ça.

   <LinearLayout
        android:id="@+id/linearButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/selector_button_translucent_ab_color"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

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

Alors appelle juste OnClickListenerleLinearLayout .

J'espère que cela aide quelqu'un car cela semble être un problème très courant. :)


1
C'est une bonne idée, mais une mauvaise solution. Vous pouvez obtenir la même chose avec un seul TextView en utilisant l'attribut drawableLeft. Cela vous permet d'afficher un dessin à gauche du texte.
muetzenflo

@muetzenflo yup, c'est vrai. mais lorsque vous faites correspondre le textView à la largeur du parent, votre dessinable se déplacera à l'extrême gauche même si vous centrez votre texte. s'il vous plaît laissez-moi savoir si je me trompe. et la question ne concerne que cela.
Ankit Popli

ah désolé..Je suis venu ici pour exactement ce problème et j'ai perdu ma concentration après avoir essayé trop de choses :) Je suppose que je n'ai pas vu la forêt pour les arbres. Ma faute!
muetzenflo

7

Vous pouvez utiliser un bouton personnalisé qui mesure et se dessine pour accueillir un dessin de gauche. Veuillez trouver un exemple et une utilisation ici

public class DrawableAlignedButton extends Button {

    public DrawableAlignedButton(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableAlignedButton(Context context) {
    super(context);
}

public DrawableAlignedButton(Context context, AttributeSet attrs, int style) {
    super(context, attrs, style);
}

private Drawable mLeftDrawable;

@Override
    //Overriden to work only with a left drawable.
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left,
        Drawable top, Drawable right, Drawable bottom) {
    if(left == null) return;
    left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
    mLeftDrawable = left;
}

@Override
protected void onDraw(Canvas canvas) {
    //transform the canvas so we can draw both image and text at center.
    canvas.save();
    canvas.translate(2+mLeftDrawable.getIntrinsicWidth()/2, 0);
    super.onDraw(canvas);
    canvas.restore();
    canvas.save();
    int widthOfText = (int)getPaint().measureText(getText().toString());
    int left = (getWidth()+widthOfText)/2 - mLeftDrawable.getIntrinsicWidth() - 2;
    canvas.translate(left, (getHeight()-mLeftDrawable.getIntrinsicHeight())/2);
    mLeftDrawable.draw(canvas);
    canvas.restore();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int height = getMeasuredHeight();
    height = Math.max(height, mLeftDrawable.getIntrinsicHeight() + getPaddingTop() + getPaddingBottom());
    setMeasuredDimension(getMeasuredWidth(), height);
}
}

Usage

<com.mypackage.DrawableAlignedButton
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableLeft="@drawable/my_drawable"
        android:gravity="center"
        android:padding="7dp"
        android:text="My Text" />

Vous pouvez inclure du code dans votre réponse, ce qui devrait être la méthode préférée (si ce n'est pas trop long), car les liens peuvent mourir avec le temps-
Lukas Knuth

2
Pas très précis mais je
suppose

Il décale un texte vers la droite, mais pas assez (une image recouvre le texte). De plus, comme les autres solutions de vue personnalisée, il n'accepte pas le texte long.
CoolMind

5

C'est ma solution que j'ai écrite il y a 3 ans. Le bouton a du texte et une icône de gauche et est dans le cadre qui est le bouton réel ici et peut être étiré par fill_parent. Je ne peux pas le tester à nouveau, mais cela fonctionnait à l'époque. Button n'a probablement pas besoin d'être utilisé et peut être remplacé par TextView mais je ne le testerai pas pour le moment et cela ne change pas trop la fonctionnalité ici.

<FrameLayout
    android:id="@+id/login_button_login"
    android:background="@drawable/apptheme_btn_default_holo_dark"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:layout_height="40dp">
    <Button
        android:clickable="false"
        android:drawablePadding="15dp"
        android:layout_gravity="center"
        style="@style/WhiteText.Small.Bold"
        android:drawableLeft="@drawable/lock"
        android:background="@color/transparent"
        android:text="LOGIN" />
</FrameLayout>

1
Maintenant je vois que je n'étais pas seul avec cette solution :)
Renetik

4

Je sais que cette question est un peu plus ancienne, mais peut-être que vous êtes toujours ouvert pour des conseils ou des solutions de contournement:

Créez un RelativeLayout "wrap_content" avec l'image du bouton comme arrière-plan ou le bouton lui-même comme premier élément de la mise en page. Obtenez un LinearLayout et définissez-le sur "layout_centerInParent" et "wrap_content". Ensuite, définissez votre Drawable comme Imageview. Enfin, définissez un TextView avec votre texte (paramètres régionaux).

donc fondamentalement vous avez cette structure:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

ou comme ça:

RelativeLayout with "android-specific" button image as background
  LinearLayout
    ImageView
    TextView

Je sais qu'avec cette solution, il y a de nombreux éléments à traiter, mais vous pouvez créer très facilement votre propre bouton personnalisé avec elle et également définir la position exacte du texte et des dessinables :)


Cette approche peut bien fonctionner. Dans mon cas, tout ce dont j'avais besoin était un RelativeLayout contenant un TextView. Le RelativeLayout a l'arrière-plan, le TextView obtient l'icône drawableLeft. Ensuite, dans le code: attachez onClickListener au RelativeLayout et findViewById pour le TextView séparément si nécessaire
Stan Kurdziel

La première structure suggérée donne l'exception «Le bouton ne peut pas être converti en ViewGroup».
Youngjae

4

Ma façon de résoudre ce problème consistait à entourer le bouton d' <View ../>éléments légers qui se redimensionnent dynamiquement. Voici quelques exemples de ce qui peut être réalisé avec ceci:

Démo par Dev-iL

Notez que la zone cliquable des boutons dans l'exemple 3 est la même que dans 2 (c'est-à-dire avec des espaces), ce qui est différent de l'exemple 4 où il n'y a pas d'espaces "non cliquables" entre les deux.

Code:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 1: Button with a background color:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_weight="0.3"/>
        <!-- Play around with the above 3 values to modify the clickable 
             area and image alignment with respect to text -->
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 2: Button group + transparent layout + spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 3: Button group + colored layout:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:text="Example 4 (reference): Button group + no spacers:"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray">
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>   
    </LinearLayout>
</LinearLayout>


2

Vous pouvez créer un widget personnalisé:

La classe Java IButton:

public class IButton extends RelativeLayout {

private RelativeLayout layout;
private ImageView image;
private TextView text;

public IButton(Context context) {
    this(context, null);
}

public IButton(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public IButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.ibutton, this, true);

    layout = (RelativeLayout) view.findViewById(R.id.btn_layout);

    image = (ImageView) view.findViewById(R.id.btn_icon);
    text = (TextView) view.findViewById(R.id.btn_text);

    if (attrs != null) {
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.IButtonStyle);

        Drawable drawable = attributes.getDrawable(R.styleable.IButtonStyle_button_icon);
        if(drawable != null) {
            image.setImageDrawable(drawable);
        }

        String str = attributes.getString(R.styleable.IButtonStyle_button_text);
        text.setText(str);

        attributes.recycle();
    }

}

@Override
public void setOnClickListener(final OnClickListener l) {
    super.setOnClickListener(l);
    layout.setOnClickListener(l);
}

public void setDrawable(int resId) {
    image.setImageResource(resId);
}

}

La mise en page ibutton.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >

<ImageView
    android:id="@+id/btn_icon"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_marginRight="2dp"
    android:layout_toLeftOf="@+id/btn_text"
    android:duplicateParentState="true" />

<TextView
    android:id="@+id/btn_text"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:duplicateParentState="true"
    android:gravity="center_vertical"
    android:textColor="#000000" />
</RelativeLayout>

Pour utiliser ce widget personnalisé:

<com.test.android.widgets.IButton
     android:id="@+id/new"
     android:layout_width="fill_parent"         
     android:layout_height="@dimen/button_height"
     ibutton:button_text="@string/btn_new"
     ibutton:button_icon="@drawable/ic_action_new" />

Vous devez fournir l'espace de noms pour les attributs personnalisés xmlns: ibutton = "http://schemas.android.com/apk/res/com.test.android.xxx" où com.test.android.xxx est le package racine de L'application.

Mettez-le simplement sous xmlns: android = "http://schemas.android.com/apk/res/android".

La dernière chose dont vous aurez besoin sont les attributs personnalisés dans le fichier attrs.xml.

Dans le fichier attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IButtonStyle">
        <attr name="button_text" />
        <attr name="button_icon" format="integer" />
    </declare-styleable>

    <attr name="button_text" />

</resources>

Pour un meilleur positionnement, enveloppez le Button personnalisé dans un LinearLayout, si vous souhaitez éviter des problèmes potentiels avec les positionnements RelativeLayout.

Prendre plaisir!


2

J'ai eu un problème similaire mais je voulais avoir un dessin au centre sans texte et sans mise en page enveloppée. La solution était de créer un bouton personnalisé et d'ajouter un autre dessinable en plus de GAUCHE, DROITE, HAUT, BAS. On peut facilement modifier le placement dessiné et l'avoir dans la position souhaitée par rapport au texte.

CenterDrawableButton.java

public class CenterDrawableButton extends Button {
    private Drawable mDrawableCenter;

    public CenterDrawableButton(Context context) {
        super(context);
        init(context, null);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs){
        //if (isInEditMode()) return;
        if(attrs!=null){
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs, R.styleable.CenterDrawableButton, 0, 0);

            try {
                setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));

            } finally {
                a.recycle();
            }

        }
    }

    public void setCenterDrawable(int center) {
        if(center==0){
            setCenterDrawable(null);
        }else
        setCenterDrawable(getContext().getResources().getDrawable(center));
    }
    public void setCenterDrawable(@Nullable Drawable center) {
        int[] state;
        state = getDrawableState();
        if (center != null) {
            center.setState(state);
            center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
            center.setCallback(this);
        }
        mDrawableCenter = center;
        invalidate();
        requestLayout();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mDrawableCenter!=null) {
            setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
                    Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
        }
    }
    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mDrawableCenter != null) {
            int[] state = getDrawableState();
            mDrawableCenter.setState(state);
            mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
                    mDrawableCenter.getIntrinsicHeight());
        }
        invalidate();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawableCenter != null) {
            Rect rect = mDrawableCenter.getBounds();
            canvas.save();
            canvas.translate(getWidth() / 2 - rect.right / 2, getHeight() / 2 - rect.bottom / 2);
            mDrawableCenter.draw(canvas);
            canvas.restore();
        }
    }
}

attrs.xml

<resources>
    <attr name="drawableCenter" format="reference"/>
    <declare-styleable name="CenterDrawableButton">
        <attr name="drawableCenter"/>
    </declare-styleable>
</resources>

usage

<com.virtoos.android.view.custom.CenterDrawableButton
            android:id="@id/centerDrawableButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:drawableCenter="@android:drawable/ic_menu_info_details"/>

Merci! C'est ce que je cherchais.
MistaGreen

pourriez-vous m'aider s'il vous plaît dans cette question, stackoverflow.com/questions/35912539/… , avec votre réponse, je suis très proche mais deux drawables apparaissent
Reprator

Cette solution place le dessinable au centre d'un bouton, juste au-dessus du texte centré.
CoolMind

1
<style name="captionOnly">
    <item name="android:background">@null</item>
    <item name="android:clickable">false</item>
    <item name="android:focusable">false</item>
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
</style>

<FrameLayout
   style="?android:attr/buttonStyle"
   android:layout_width="match_parent"
   android:layout_height="wrap_content" >

    <Button
       style="@style/captionOnly"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:drawableLeft="@android:drawable/ic_delete"
       android:gravity="center"
       android:text="Button Challenge" />
</FrameLayout>

Placez le FrameLayout dans LinearLayout et définissez l'orientation sur Horizontal.


1

Vous pouvez placer le bouton sur un LinearLayout

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/activity_login_fb_height"
        android:background="@mipmap/bg_btn_fb">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/lblLoginFb"
                android:textColor="@color/white"
                android:drawableLeft="@mipmap/icon_fb"
                android:textSize="@dimen/activity_login_fb_textSize"
                android:text="Login with Facebook"
                android:gravity="center" />
        </LinearLayout>
        <Button
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/btnLoginFb"
            android:background="@color/transparent"
            />
    </RelativeLayout>

0

Que se passe-t-il si vous essayez android: gravity = "center_horizontal"?


5
Ça ne marche pas. Le texte est quelque peu centré mais le drawableLeft reste sur le côté gauche.
Peter Ajtai

0

Je pense que Android: gravity = "center" devrait fonctionner


6
Ça ne marche pas pour moi. Il centre le texte, mais le drawableLeft reste à l'extrême gauche.
Peter Ajtai

Vous devez déclarer l'icône et le texte sous le même parent, utilisez android: gravity = "center" pour le parent
devanshu_kaushik

0

Comme suggéré par Rodja, avant la version 4.0, il n'y avait pas de moyen direct de centrer le texte avec le dessinable. Et en effet, la définition d'une valeur padding_left éloigne le dessinable de la bordure. Par conséquent, ma suggestion est que lors de l'exécution, vous calculez exactement combien de pixels de la bordure gauche votre dessinable doit être, puis passez-le en utilisant setPadding Votre calcul peut être quelque chose comme

int paddingLeft = (button.getWidth() - drawableWidth - textWidth) / 2;

La largeur de votre dessin est fixe et vous pouvez la rechercher et vous pouvez également calculer ou deviner la largeur du texte.

Enfin, vous devez multiplier la valeur de remplissage par la densité de l'écran, ce que vous pouvez faire à l'aide de DisplayMetrics



0

public class DrawableCenterTextView étend TextView {

public DrawableCenterTextView(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
}

public DrawableCenterTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public DrawableCenterTextView(Context context) {
    super(context);
}

@Override
protected void onDraw(Canvas canvas) {
    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) {
        Drawable drawableLeft = drawables[0];
        Drawable drawableRight = drawables[2];
        if (drawableLeft != null || drawableRight != null) {
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            if (drawableLeft != null)
                drawableWidth = drawableLeft.getIntrinsicWidth();
            else if (drawableRight != null) {
                drawableWidth = drawableRight.getIntrinsicWidth();
            }
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        }
    }
    super.onDraw(canvas);
}

}


Cela n'a pas du tout fonctionné pour moi. Pouvez-vous s'il vous plaît montrer un exemple? Peut-être que je ne l'utilise pas correctement
développeur Android

0

Correctif sale.

android:paddingTop="10dp"
android:drawableTop="@drawable/ic_src"

Trouver le bon rembourrage résout le but. Cependant, pour un écran varié, utilisez un remplissage différent et placez-le dans la ressource dimens dans le dossier de valeurs respectif.


0

Utilisez RelativeLayout (conteneur) et android: layout_centerHorizontal = "true" , mon exemple:

                <RelativeLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1" >

                    <CheckBox
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerHorizontal="true"
                        android:layout_gravity="center"
                        android:layout_marginBottom="5dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginTop="5dp"
                        android:button="@drawable/bg_fav_detail"
                        android:drawablePadding="5dp"
                        android:text=" Favorite" />
                </RelativeLayout>

0

Autre possibilité de conserver le thème Button.

<Button
            android:id="@+id/pf_bt_edit"
            android:layout_height="@dimen/standard_height"
            android:layout_width="match_parent"
            />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_alignBottom="@id/pf_bt_edit"
            android:layout_alignLeft="@id/pf_bt_edit"
            android:layout_alignRight="@id/pf_bt_edit"
            android:layout_alignTop="@id/pf_bt_edit"
            android:layout_margin="@dimen/margin_10"
            android:clickable="false"
            android:elevation="20dp"
            android:gravity="center"
            android:orientation="horizontal"
            >

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:adjustViewBounds="true"
                android:clickable="false"
                android:src="@drawable/ic_edit_white_48dp"/>

            <TextView
                android:id="@+id/pf_tv_edit"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="@dimen/margin_5"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/pf_bt_edit"/>

        </LinearLayout>

Avec cette solution, si vous ajoutez @ color / your_color @ color / your_highlight_color dans votre thème d'activité, vous pouvez avoir le thème Matherial sur Lollipop avec ombre et ondulation, et pour la version précédente, bouton plat avec votre couleur et votre couleur de surbrillance lorsque vous appuyez dessus.

De plus, avec cette solution, la redimensionnement automatique de l'image

Résultat: Premier sur l'appareil Lollipop Deuxième: Sur l'appareil pré-sucette 3ème: Appuyez sur le bouton de l'appareil Pré-sucette

entrez la description de l'image ici


0

J'ai centré textViewavec l'icône en utilisant paddingLeftet et en alignant textView à gauche | centerVertical . et pour un petit écart entre la vue et l'icône, j'ai utilisédrawablePadding

         <Button
            android:id="@+id/have_it_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/textbox"
            android:drawableLeft="@drawable/have_it"
            android:drawablePadding="30dp"
            android:gravity="left|center_vertical"
            android:paddingLeft="60dp"
            android:text="Owner Contact"
            android:textColor="@android:color/white" />

2
Cela ne fonctionnera pas sur de nombreux écrans, uniquement sur celui pour lequel a android:paddingLeftfonctionné.
soshial

0

Cela peut être un fil ancien / fermé, mais j'ai cherché partout, je n'ai pas trouvé quelque chose d'utile, jusqu'à ce que je décide de créer ma propre solution. S'il y a quelqu'un ici qui essaie de chercher une réponse, essayez celle-ci, cela pourrait vous faire gagner une minute de réflexion

          <LinearLayout
            android:id="@+id/llContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/selector"
            android:clickable="true"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="10dp"
            android:textStyle="bold">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="This is a text" />

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


        </LinearLayout>

Étant donné que la mise en page linéaire agit comme le conteneur et celui qui a le sélecteur, lorsque vous cliquez sur la mise en page linéaire entière, elle ressemblerait à ce qu'elle devrait être. si vous voulez qu'il soit à la fois centré, utilisez l'insteaf relative. Si vous voulez qu'il soit centré horizontalement, changez l'orientation en horizontal.

Prenez note N'OUBLIEZ PAS d'ajouter android: clickable = "true" à votre conteneur principal (relatif ou linéaire) pour que l'action se déroule.

Encore une fois, cela peut être un vieux fil mais peut encore aider quelqu'un là-bas.

-cheers espère que cela aide- happycodings.


0

Si vous utilisez l'une des solutions de vue personnalisée , soyez prudent, car elles échouent souvent sur du texte long ou multiligne . J'ai réécrit quelques réponses, remplacé onDraw()et compris que c'était une mauvaise façon.


0

J'ai vu des solutions pour aligner drawable au début / gauche mais rien pour drawable end / right, alors j'ai trouvé cette solution. Il utilise des rembourrages calculés dynamiquement pour aligner le dessin et le texte sur les côtés gauche et droit.

class IconButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.buttonStyle
) : AppCompatButton(context, attrs, defStyle) {

    init {
        maxLines = 1
    }

    override fun onDraw(canvas: Canvas) {
        val buttonContentWidth = (width - paddingLeft - paddingRight).toFloat()

        val textWidth = paint.measureText(text.toString())

        val drawable = compoundDrawables[0] ?: compoundDrawables[2]
        val drawableWidth = drawable?.intrinsicWidth ?: 0
        val drawablePadding = if (textWidth > 0 && drawable != null) compoundDrawablePadding else 0
        val bodyWidth = textWidth + drawableWidth.toFloat() + drawablePadding.toFloat()

        canvas.save()

        val padding = (buttonContentWidth - bodyWidth).toInt() / 2
        val leftOrRight = if (compoundDrawables[0] != null) 1 else -1
        setPadding(leftOrRight * padding, 0, -leftOrRight * padding, 0)

        super.onDraw(canvas)
        canvas.restore()
    }
}

Il est important de définir la gravité dans votre mise en page sur "center_vertical | start" ou "center_vertical | end" selon l'endroit où vous définissez l'icône. Par exemple:

<com.stackoverflow.util.IconButton
        android:id="@+id/cancel_btn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableStart="@drawable/cancel"
        android:drawablePadding="@dimen/padding_small"
        android:gravity="center_vertical|start"
        android:text="Cancel" />

Le seul problème avec cette implémentation est que le bouton ne peut avoir qu'une seule ligne de texte, sinon la zone du texte remplit le bouton et les remplissages seront de 0.


-5

utilisez ceci android:background="@drawable/ic_play_arrow_black_24dp"

il suffit de définir l'arrière-plan sur l'icône que vous souhaitez centrer

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.