【问题标题】:Android: how to create a button with image and text that are both centredAndroid:如何创建一个带有居中图像和文本的按钮
【发布时间】:2012-04-15 14:54:47
【问题描述】:

我遇到了一个奇怪的 Android 问题 - 我想要一个如下所示的按钮:

 |-----------------------------------------------------------------------|
 |                   [icon] <5px> [text text text]                       |
 |-----------------------------------------------------------------------|

并且组([icon] [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 布局引擎手中接过布局责任

没有更优雅的解决方案吗?

【问题讨论】:

  • 希望你已经解决了你的问题

标签: android image layout button text


【解决方案1】:

我在 eclipse 中试过了,没有报错:

<Button android:id="@+id/test"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent" >
<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:gravity="center" 
    android:background="@android:color/transparent" >

    </LinearLayout>
    </Button>

因此,我想您可以在布局中添加图像和文本视图,将其本身添加到按钮中,并将布局居中。

最好的问候。

【讨论】:

  • hmmm ...我试过这个,但在模拟器上运行它时出现 java.lang.ClassCastException(符合 2.3.3)
  • Button 不能容纳 LinearLayout,因为它不是 ViewGroup。这行不通。
【解决方案2】:

您也可以考虑使用自定义视图来创建自定义按钮。

这可能是从简单到极其复杂的任何地方。

如果您需要做的只是覆盖onDraw(),那就很容易了。如果需要布局多个视图会更复杂。

【讨论】:

  • 我会接受这个答案,因为它是正确的并且提供了一个解决方案,尽管我不确定我是否可以将它归类为“更优雅”的解决方案。我的观点是,当您调用 setGravity(CENTER) 并为此创建自定义组件时,期望文本和图标居中实际上是一种常识,这有点矫枉过正。
【解决方案3】:

你可以使用下面的Button子类来实现这个效果。

  1. 将此类粘贴到您的项目中,并根据需要调整包名称。
    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。如果您想在可绘制对象和文本之间添加填充,请将以下内容添加到您的活动的onCreate

    // Anywhere after setContentView(...)
    IconButton button = (IconButton)findViewById(R.id.search);
    button.setIconPadding(10);

这个子类也支持drawableRight。它不支持多个可绘制对象。

如果您想要更多功能,例如能够直接在您的布局 XML 中指定 iconPadding,我有一个 library that supports this.

【讨论】:

    【解决方案4】:

    简单的方法是在LinearLayout中写Button。像这样的

     <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center">
    
                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:drawableLeft="@drawable/ic_left"
                    android:drawablePadding="5dp"
                    android:duplicateParentState="true"
                    android:text="Button text"/>
    
            </LinearLayout>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-07
      • 2018-04-16
      • 2015-04-23
      • 1970-01-01
      • 2012-09-03
      • 2011-10-11
      • 2011-04-07
      相关资源
      最近更新 更多