我遇到了一个奇怪的 Android 问题 - 我想要一个看起来像这样的按钮:
|-----------------------------------------------------------------------|
| [icon] <5px> [text text text] |
|-----------------------------------------------------------------------|
和组 ([icon] <5px> [text text text]) 应该居中。请注意,5px 仅用作您希望在图标和文本之间的任何填充的占位符
我在这里找到了一些答案,这些答案或多或少地围绕着设置背景(我不想这样做,因为我有另一个背景)或使用 android:drawableLeft 属性来设置图标。
然而,setCompoundDrawablesWithIntrinsicBounds 方法的文档看起来有点误导 (see here) .它指出图像位于 TEXT 的左/右/上/下侧,这是不正确的。该图标位于 BUTTON 的相应侧。例如:
设置 android:drawableLeft 属性将图标放在最左边的位置并让我得到这个(重力中心):
|-----------------------------------------------------------------------|
| [icon] [text text text] |
|-----------------------------------------------------------------------|
或者这个(重力向左):
|-----------------------------------------------------------------------|
| [icon] [text text text] |
|-----------------------------------------------------------------------|
两个都很丑:(
我找到了一个看起来像这样的解决方法:
public static void applyTextOffset(Button button, int buttonWidth) {
int textWidth = (int) button.getPaint().measureText(button.getText().toString());
int padding = (buttonWidth / 2) - ((textWidth / 2) + Constants.ICON_WIDTH + Constants.ICON_TO_TEXT_PADDING);
button.setPadding(padding, 0, 0, 0);
button.setCompoundDrawablePadding(-padding);
}
它或多或少地工作,但我不喜欢它,原因如下:
- 它需要知道按钮的宽度。使用自动调整大小的按钮,直到实际布局完成后才会知道。 Google 建议在渲染完成后使用监听器了解实际宽度,但这会使代码非常复杂。
- 我觉得我正在接管 Android 布局引擎的布局责任
有没有更优雅的解决方案?
最佳答案
您可以使用以下Button
子类来实现此效果。
- 将此类粘贴到您的项目中,并根据需要调整包名称。
package com.phillipcalvin.iconbutton;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.Button;
public class IconButton extends Button {
protected int drawableWidth;
protected DrawablePositions drawablePosition;
protected int iconPadding;
// Cached to prevent allocation during onLayout
Rect bounds;
private enum DrawablePositions {
NONE,
LEFT,
RIGHT
}
public IconButton(Context context) {
super(context);
bounds = new Rect();
}
public IconButton(Context context, AttributeSet attrs) {
super(context, attrs);
bounds = new Rect();
}
public IconButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
bounds = new Rect();
}
public void setIconPadding(int padding) {
iconPadding = padding;
requestLayout();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Paint textPaint = getPaint();
String text = getText().toString();
textPaint.getTextBounds(text, 0, text.length(), bounds);
int textWidth = bounds.width();
int contentWidth = drawableWidth + iconPadding + textWidth;
int contentLeft = (int)((getWidth() / 2.0) - (contentWidth / 2.0));
setCompoundDrawablePadding(-contentLeft + iconPadding);
switch (drawablePosition) {
case LEFT:
setPadding(contentLeft, 0, 0, 0);
break;
case RIGHT:
setPadding(0, 0, contentLeft, 0);
break;
default:
setPadding(0, 0, 0, 0);
}
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) {
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
if (null != left) {
drawableWidth = left.getIntrinsicWidth();
drawablePosition = DrawablePositions.LEFT;
} else if (null != right) {
drawableWidth = right.getIntrinsicWidth();
drawablePosition = DrawablePositions.RIGHT;
} else {
drawablePosition = DrawablePositions.NONE;
}
requestLayout();
}
}
2。修改您的布局以使用这个新的子类而不是普通的 Button
:
<com.phillipcalvin.iconbutton.IconButton
android:id="@+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/search"
android:text="@string/search" />
3。如果您想在可绘制对象和文本之间添加填充,请将以下内容添加到 Activity 的 onCreate
:
// Anywhere after setContentView(...)
IconButton button = (IconButton)findViewById(R.id.search);
button.setIconPadding(10);
这个子类也支持drawableRight
。它不支持多个可绘制对象。
如果您想要更多功能,例如能够直接在您的布局 XML 中指定 iconPadding
,我有一个 library that supports this.
关于Android:如何创建一个图像和文本都居中的按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9968094/