Как иметь центр изображения и текста внутри кнопки

Я хочу отображать TEXT и Icon на кнопке.

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

Я попытался с

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

Но Text и Icon не в центре.
Размер моего Text зависит от размера текста. Icon и Text должны быть скорректированы в центр.

Как я должен это делать?

Solutions Collecting From Web of "Как иметь центр изображения и текста внутри кнопки"

Вы можете подделать его, сделав более сложный макет, но я не уверен, стоит ли это. Вот что я взломал вместе:

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

Там может быть более сжатый способ сделать это. Я, как правило, пытаюсь заставить RelativeLayout делать то, что я хочу, иногда. Обратите внимание, что вам нужно обратить внимание на z-порядок (кнопка должна появиться на верхнем уровне RelativeLayout), и вам может потребоваться настроить отступы, чтобы заставить его выглядеть так, как вы хотите.

Как и некоторые другие подходы, я считаю, что хорошим решением является расширение Button и добавление недостающих функциональных возможностей путем переопределения его метода onLayout :

 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); } } } 

Образец работает только для левого и правого рисования, но может быть расширен для настройки верхних и нижних чертежей.

Как насчет этого?

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

Это должно работать

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

Как об использовании SpannableString в качестве текста с 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); 

Вы можете просто установить отступы в зависимости от размера и размера кнопки:

 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… 

Легкий способ (хотя и не идеальный) – установить paddingRight на ту же ширину, что и значок.

Это то, что я сделал … Это можно улучшить. Текст центрирован, а значок – влево. Поэтому они оба не сосредоточены как группа.

 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); } } 
 <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> 
 android:layout_gravity="center_vertical|center_horizontal|center" >