How to have the center of the image and text inside the button

I want to display TEXT and Icon on a button.

 +----------------------------+ | Icon TEXT | +----------------------------+ 

I tried using

 <Button android:id="@+id/Button01" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="40dip" android:text="TEXT" android:drawableLeft="@drawable/Icon" /> 

But TEXT and Icon not in the center.
My TEXT size varies, according to the size of the Icon text and TEXT should be set to the center.

How should I do it?

+42
android
Jan 27 2018-11-11T00:
source share
11 answers

You can fake it by making a more complex layout, but I'm not sure if it is worth it. Here's something I hacked together:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_alignTop="@+id/foreground" android:layout_alignBottom="@id/foreground" android:layout_alignRight="@id/foreground" android:layout_alignLeft="@id/foreground" android:onClick="clickedMe" /> <RelativeLayout android:id="@id/foreground" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/button_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="@string/hello" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toLeftOf="@id/button_text" android:paddingTop="10dip" android:paddingBottom="10dip" android:src="@drawable/icon" /> </RelativeLayout> </RelativeLayout> 

There may be a more concise way to do this. I often try to get RelativeLayout to do what I want. Note that you need to pay attention to the z-order (the button should appear first at the top level of the RelativeLayout), and you may need to adjust the indentation to make it look the way you want.

+33
Apr 02 2018-11-11T00:
source share

Like some other approaches, I find that a good solution is to extend Button and add the missing functionality by overriding the onLayout method:

 public class CenteredIconButton extends Button { private static final int LEFT = 0, TOP = 1, RIGHT = 2, BOTTOM = 3; // Pre-allocate objects for layout measuring private Rect textBounds = new Rect(); private Rect drawableBounds = new Rect(); public CenteredIconButton(Context context) { this(context, null); } public CenteredIconButton(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.buttonStyle); } public CenteredIconButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (!changed) return; final CharSequence text = getText(); if (!TextUtils.isEmpty(text)) { TextPaint textPaint = getPaint(); textPaint.getTextBounds(text.toString(), 0, text.length(), textBounds); } else { textBounds.setEmpty(); } final int width = getWidth() - (getPaddingLeft() + getPaddingRight()); final Drawable[] drawables = getCompoundDrawables(); if (drawables[LEFT] != null) { drawables[LEFT].copyBounds(drawableBounds); int leftOffset = (width - (textBounds.width() + drawableBounds.width()) + getRightPaddingOffset()) / 2 - getCompoundDrawablePadding(); drawableBounds.offset(leftOffset, 0); drawables[LEFT].setBounds(drawableBounds); } if (drawables[RIGHT] != null) { drawables[RIGHT].copyBounds(drawableBounds); int rightOffset = ((textBounds.width() + drawableBounds.width()) - width + getLeftPaddingOffset()) / 2 + getCompoundDrawablePadding(); drawableBounds.offset(rightOffset, 0); drawables[RIGHT].setBounds(drawableBounds); } } } 

The sample works only for the left and right drawings, but can be expanded to adjust the upper and lower drawings.

+28
Mar 02 '14 at 17:28
source share

How about this?

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/lovely_color" android:clickable="true" android:onClick="clickHandler"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="no?" android:textColor="@color/white" android:layout_centerHorizontal="true" android:drawableLeft="@drawable/lovely_icon" android:drawablePadding="10dp" android:padding="10dp" android:gravity="center" android:textSize="21sp"/> </RelativeLayout> 
+17
Oct 31 '12 at 17:43
source share

This should work

 <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal"> <TextView android:id="@+id/button_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="hello" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="10dip" /> </LinearLayout> 
+5
Apr 04 2018-11-11T00:
source share

How to use SpannableString as text with ImageSpan?

 Button myButton = ... SpannableString ss = new SpannableString(" " + getString(R.string.my_button_text)); Drawable d = getResources().getDrawable(R.drawable.myIcon); d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); ImageSpan span = new ImageSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM); ss.setSpan(span, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); myButton.setText(ss); 
+4
Sep 08 '14 at 4:53 on
source share

You can simply install the add-on depending on the size and size of the button:

 Button button1 = null; //initialize button…. ViewGroup.LayoutParams params = button1.getLayoutParams(); int btn1Width = ((int) (0.33 * (double)ecranWidth)); params.width = btn1Width; button1.setLayoutParams(params); button1.setPadding((btn1Width/2-9), 0, 0, 0); //where (btn1Width/2-9) = size of button divided on 2 minux half size of icon… 
+1
Dec 13 '11 at 16:35
source share

An easy way (though not perfect) is to set the paddingRight to the same width as the icon.

+1
Jul 04 2018-12-12T00:
source share

This is what I did ... It can be improved. The text is centered and the icon to the left. Therefore, they are both not focused as a group.

 public class CustomButton extends Button { Rect r = new Rect(); private Drawable buttonIcon = null; private int textImageSeparation = 10; public CustomButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); } public CustomButton(Context context) { super(context); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); Drawable icon = getButtonIcon(); if(icon != null) { int drawableHeight = icon.getIntrinsicHeight(); int drawableWidth = icon.getIntrinsicWidth(); if(icon instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable)icon).getBitmap(); drawableWidth = (int) AndroidScreenUtils.dipToPixels(bitmap.getWidth()); drawableHeight = (int) AndroidScreenUtils.dipToPixels(bitmap.getHeight()); } else { drawableWidth = (int) AndroidScreenUtils.dipToPixels(icon.getIntrinsicWidth()); drawableHeight = (int) AndroidScreenUtils.dipToPixels(icon.getIntrinsicHeight()); } float textWidth = getLayout().getPaint().measureText(getText().toString()); float left = ((getWidth() - textWidth) / 2) - getTextImageSeparation() - drawableWidth; int height = getHeight(); int top = (height - drawableHeight) /2; int right = (int) (left + drawableWidth); int bottom = top + drawableHeight; r.set((int) left, top, right, bottom); icon.setBounds(r); icon.draw(canvas); } } private Drawable getButtonIcon() { return buttonIcon; } public void setButtonIcon(Drawable buttonIcon) { this.buttonIcon = buttonIcon; } private int getTextImageSeparation() { return textImageSeparation; } public void setTextImageSeparation(int dips) { this.textImageSeparation = (int) AndroidScreenUtils.dipToPixels(dips); } } 
0
06 Sep '12 at 23:45
source share
 <LinearLayout style="@style/Sonnen.Raised.Button.Transparent.LightBlueBorder" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="30dp" android:orientation="horizontal" android:padding="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:drawableLeft="@drawable/refresh" android:drawablePadding="10dp" android:drawableStart="@drawable/refresh" android:gravity="center" android:text="@string/generic_error_button_text" android:textColor="@color/dark_sky_blue" android:textSize="20sp"/> </LinearLayout> 
0
Dec 08 '15 at 11:22
source share

I made a custom component to solve this problem.

Component Class:

 class CustomImageButton @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0 ) : RelativeLayout(context, attrs, defStyleAttr, defStyleRes) { init { inflate(context, R.layout.custom_image_button, this) // Load the styled attributes and set their properties val typedArray = context.obtainStyledAttributes( attrs, R.styleable.CustomImageButton, defStyleAttr, 0 ) val src = typedArray?.getDrawable(R.styleable.CustomImageButton_cib_src) val text = typedArray?.getText(R.styleable.CustomImageButton_cib_text) val contentDescription = typedArray?.getText(R.styleable.CustomImageButton_cib_contentDescription) ivIcon.setImageDrawable(src) tvText.text = text ivIcon.contentDescription = contentDescription typedArray?.recycle() } } 

XML component:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:toos="http://schemas.android.com/tools" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_width="fill_parent" android:layout_height="@dimen/button_height"> <Button android:id="@+id/bClick" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_alignTop="@+id/foreground" android:layout_alignBottom="@id/foreground" android:layout_alignEnd="@id/foreground" android:layout_alignStart="@id/foreground"/> <RelativeLayout android:id="@id/foreground" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tvText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="@color/textWhite" toos:text="Some text to test" toos:ignore="RelativeOverlap"/> <ImageView android:id="@+id/ivIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toStartOf="@id/tvText" android:paddingTop="1dip" android:paddingBottom="1dip" android:src="@mipmap/some_image_to_test" toos:ignore="ContentDescription"/> </RelativeLayout> </RelativeLayout> 

Component usage example:

 <app.package.components.CustomImageButton android:id="@+id/cibMyImageButton" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content" android:layout_width="match_parent" app:cib_src="@mipmap/my_image_to_put_in_the_button" app:cib_text="Some text to show in the button" app:cib_contentDescription="icon description"/> 
0
Dec 12 '18 at 15:27
source share
 android:layout_gravity="center_vertical|center_horizontal|center" > 

-5
Jan 27 2018-11-11T00:
source share



All Articles