How to center icon and text in a android button with width set to "fill parent"

199,097

Solution 1

All the previous answers seem to be outdated

You can use the MaterialButton now which lets setting the icon gravity.

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

enter image description here

For using the material components you will obviously need to:

Add a dependency implementation 'com.google.android.material:material:1.3.0-alpha01' (use latest version)

Make your theme extend Material Components theme

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

In case you cannot do so, extend it from the Material Bridge theme

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

Solution 2

android:drawableLeft is always keeping android:paddingLeft as a distance from the left border. When the button is not set to android:width="wrap_content", it will always hang to the left!

With Android 4.0 (API level 14) you can use android:drawableStart attribute to place a drawable at the start of the text. The only backward compatible solution I've come up with is using an ImageSpan to create a Text+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);

In my case I needed to also adjust the android:gravity attribute of the Button to make it look centered:

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

Solution 3

I know I am late in answering this question, but this helped me:

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

I found this solution from here: Android UI struggles: making a button with centered text and icon

enter image description here

Solution 4

I used LinearLayout instead of Button. The OnClickListener, which I need to use works fine also for 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>

Solution 5

I adjust it by adding padding left and right as follows:

<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"
            />
Share:
199,097
jloriente
Author by

jloriente

Software developer interested in: nodejs, Java, Android, iOS, Web and Mobile

Updated on July 08, 2022

Comments

  • jloriente
    jloriente almost 2 years

    I want to have an Android Button with icon+text centered inside it. I'm using the drawableLeft attribute to set the image, this works well if the button has a width of "wrap_content" but I need to stretch to max width so I use width "fill_parent". This moves my icon straight to the left of the button and I want both icon and text centered inside the button.

    I've try setting up the padding but this only allows to give a fixed value so it is not what I need. I need to have icon+text aligned in the center.

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

    Any suggestions on how I could achieve that?

    • jloriente
      jloriente over 13 years
      It's possible that there is not an easy solution for this? Do I have to try with a 9patch button img with the icon in there?
    • Octavian Damiean
      Octavian Damiean over 13 years
      This might be a solution. Is the button text going to be localized or static?
    • jloriente
      jloriente over 13 years
      It's localized. There is not any other solution for this? I managed to do it with a 9 patch but having problems when changing locale.
    • Francesco
      Francesco almost 10 years
      What about using a Button with drawable TOP and adding some padding to it?
    • Muhammad Babar
      Muhammad Babar over 9 years
      bad framework design
  • Peter Ajtai
    Peter Ajtai over 12 years
    Doesn't work for me. It centers the text, but the drawableLeft remains on the very left.
  • Peter Ajtai
    Peter Ajtai over 12 years
    It doesn't work. The text is somewhat centered but the drawableLeft sticks to the left side.
  • devanshu_kaushik
    devanshu_kaushik over 12 years
    You have to declare the icon and text under the same parent, use android:gravity = "centre" for the parent
  • Stan Kurdziel
    Stan Kurdziel over 11 years
    This approach can work well. In my case, all I needed was a RelativeLayout containing a TextView. The RelativeLayout got the background, the TextView gets the drawableLeft icon. Then in the code: attach onClickListener to the RelativeLayout and findViewById for the TextView separately if needed
  • AlexD
    AlexD over 11 years
    Nice. The last line should be button.setText(buttonLabel)
  • Lukas Knuth
    Lukas Knuth about 11 years
    You can include code in your answer, which should be the preferred way (if it's not too long), as links might die over time-
  • GLee
    GLee over 10 years
    Unicode has an extensive set of character icons that are compatible with strings in Android. If you can find an acceptable one, this is a simple solution, and it has the added bonus that it will scale with text size. For instance, it has an envelope for an email icon and a couple of different phones for a call button.
  • Craig McMahon
    Craig McMahon over 10 years
    This ImageSpan solution is wonderful for solving the problem of creating a Button subclass capable of displaying either an image or text. Thanks!
  • muetzenflo
    muetzenflo over 10 years
    This is a good idea, but a bad solution. You can achieve the same thing with just one TextView using the drawableLeft-attribute. This enables you to view a drawable to the left of the text.
  • Ankit Popli
    Ankit Popli over 10 years
    @muetzenflo yup, that's right. but when you make the textView match the parent width your drawable will move to extreme left even if you center your text. please let me know if i'm wrong. and the question is about that only.
  • muetzenflo
    muetzenflo over 10 years
    ah sorry..I came here for exactly this problem and lost focus after trying out too many things :) Guess I didn't see the forest for the trees. My fault!
  • Justin
    Justin over 9 years
    I'm confused how this worked for anyone, for me it draws 2 icons... one way to the left, and one directly in the center which displays on top of the text.
  • Clive Jefferies
    Clive Jefferies over 9 years
    The problem with this is that the button is not the width of the frame layout.
  • M Dapp
    M Dapp over 9 years
    drawableStart won't work. See this thread: stackoverflow.com/questions/15350990/… Also, it seems that when you set the text using a spannable, the style is ignored.
  • Alex Semeniuk
    Alex Semeniuk over 9 years
    Not very accurate but I take it
  • Tushar Pandey
    Tushar Pandey about 9 years
    Question : AnyThing to center ImageSpan.
  • Renetik
    Renetik about 9 years
    Now I see that I was not alone with this solution :)
  • MistaGreen
    MistaGreen almost 9 years
    Thanks! That's what I was looking for.
  • Silvia H
    Silvia H almost 9 years
    drawableStart doesn't work, and it was added in API level 17 to support rtl
  • Youngjae
    Youngjae over 8 years
    First suggested structure gives "Button cannot be cast to ViewGroup" Exception.
  • Reprator
    Reprator about 8 years
    would u please help me in this question, stackoverflow.com/questions/35912539/…, with your answer i am very close to it but two drawables appears
  • android developer
    android developer almost 8 years
    This didn't work for me at all. Can you please show an example? Maybe I don't use it correctly
  • soshial
    soshial about 7 years
    This will not work on many screens, only on the one, for which android:paddingLeft worked.
  • CoolMind
    CoolMind about 6 years
    This solution places drawable in the center of a button, just over centered text.
  • CoolMind
    CoolMind about 6 years
    This solution places an icon over first symbol of a text and ignores padding. It ignores vertical alignment. Author preferred to add spaces (" ") before button text.
  • CoolMind
    CoolMind about 6 years
    It shifts a text right, but not enough (an image overlaps the text). Also, as other custom view's solutions, it doesn't accept long text right.
  • Arrie
    Arrie over 5 years
    The paddingLeft and paddingRight was that helped me with my centering. upvoting for easy solution.
  • Jacks
    Jacks over 5 years
    How do you manage the fact that your width is dynamic ? If you rotate your screen, all your icons won't be centered right ? I'm facing this issue actually
  • Dody Rachmat Wicaksono
    Dody Rachmat Wicaksono about 4 years
    this is the best answer!
  • Black_Zerg
    Black_Zerg almost 4 years
    Thanks! You saved my day! Works fine
  • Lumii
    Lumii about 3 years
    Instead of having to make change to entire app theme, you may just apply the theme only for the button itself by using app:theme on MaterialButton tag