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

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

Posted by: admin March 11, 2020 Leave a comment

Questions:

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?

How to&Answers:

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

Answer:

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

Answer:

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>

Answer:

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

Edit:

For using the material components you will obviously need to:

Add a dependency
implementation 'com.google.android.material:material:1.1.0-alpha10' (last 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>

Answer:

I recently bumped into the same problem. Tried to find a cheaper solution so came up with this.

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

Then just call the OnClickListener on LinearLayout.

Hope this helps someone as it seems like a very common problem. 🙂

Answer:

You could use a custom button which measures and draws itself to accomodate a left drawable. Please find example and usage here

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

Answer:

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

Answer:

I know this question is a bit older, but perhaps you’re still open for hints or workarounds:

Create a RelativeLayout “wrap_content” with the button image as the background or the button itself as the first element of the layout. Get a LinearLayout and set it to “layout_centerInParent” and “wrap_content”. Then set your Drawable as an Imageview. At last set a TextView with your text (locale).

so basically you have this structure:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

or like this:

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

I know with this solution there are many elements to deal with, but you can create very easy your own custom button with it and also set the exact position of text and drawables 🙂

Answer:

My way of solving it involved surrounding the the button with lightweight <View ../> elements that resize dynamically. Below are several examples of what can be achieved with this:

Demo by Dev-iL

Note that the clickable area of the buttons in example 3 is the same as in 2 (i.e. with spaces), which is different from example 4 where there are no “unclickable” gaps in between.

Code:

Answer:

This is my solution I wrote 3 years ago. Button has text and left icon and is in frame that is actual button here and can be stretched by fill_parent. I cannot test it again but it was working back then. Probably Button don’t have to be used and can be replaced by TextView but I will not test it right now and it doesn’t change functionality too much here.

Answer:

You can create a custom widget:

The Java class IButton:

}

The layout ibutton.xml

In order to use this custom widget:

You have to provide the namespace for the custom attributes
xmlns:ibutton=”http://schemas.android.com/apk/res/com.test.android.xxx”
where com.test.android.xxx is the root package of the application.

Just put it below xmlns:android=”http://schemas.android.com/apk/res/android”.

The last thing you gonna need are the custom attributes in the attrs.xml.

In the attrs.xml

For better positioning, wrap the custom Button inside a LinearLayout, if you want to avoid potential problems with RelativeLayout positionings.

Enjoy!

Answer:

Had similar issue but wanted to have center drawable with no text and no wrapped layouts. Solution was to create custom button and add one more drawable in addition to LEFT, RIGHT, TOP, BOTTOM. One can easily modify drawable placement and have it in desired position relative to text.

CenterDrawableButton.java

attrs.xml

usage

Answer:

Try to use this library

OmegaCenterIconButton

enter image description here

Answer:

Put the FrameLayout in LinearLayout and set orientation to Horizontal.

Answer:

You could put the button over a LinearLayout

Answer:

I have centered textView with icon using paddingLeft and and aligning textView to left|centerVertical. and for a small gap between view and icon i used drawablePadding

Answer:

What happens if you try android:gravity=”center_horizontal”?

Answer:

I think android:gravity= “centre” should work

Answer:

As suggested by Rodja, prior to 4.0 there isn’t a direct way to center the text with the drawable. And indeed setting a padding_left value does move the drawable away from the border. Therefore my suggestion is that on runtime you calculate exactly how many pixels from the left border your drawable needs to be and then pass it using setPadding
Your calculation may be something like

The width of your drawable’s is fixed and you can look it up and you can also calculate or guess the text width.

Finally, you would need to multiple the padding value by the screen density, which you can do using DisplayMetrics

Answer:

I dont’t test it but seems that you can use CenteredContentButton library

Answer:

public class DrawableCenterTextView extends TextView {

}

Answer:

Dirty fix.

Figuring right padding solve the purpose. However, for varied screen, use different padding and put that in dimens resource in respective value folder.

Answer:

Use RelativeLayout (container) and android:layout_centerHorizontal=”true”
,my sample:

Answer:

Other possibility to keep Button theme.

With this solution if your add
@color/your_color
@color/your_highlight_color
in your activity theme, you can have Matherial theme on Lollipop whith shadow and ripple, and for previous version flat button with your color and highlight coor when you press it.

Moreover, with this solution autoresize of picture

Result :
First on Lollipop device
Second : On pre lollipop device
3th : Pre lollipop device press button

enter image description here

Answer:

This may be an old/closed thread but I’ve search everywhere didnt find something useful, until I decided to create my own solution. If theres anyone here trying to look for answer try this one, might save you a minute of thinking

Because Linear layout act as the container and the one who has the selector, when you click the entire linear layout it would look just how it should it be. if you want it to be both centered, use relative insteaf. If you want it centered horizontally change the orientation to horizontal.

Take note DO NOT forget to add android:clickable=”true” to your main container (relative or linear) for the action to take place.

Again this may be old thread but may still help someone there.

-cheers hope it helps-
happycodings.

Answer:

If you use one of custom view’s solutions, be careful, because they often fail on long or multiline text. I rewrote some answers, replaced onDraw() and understood that that was a wrong way.

Answer:

use this
android:background="@drawable/ic_play_arrow_black_24dp"

just set the background to the icon you want to center