如何将宽度设置为“填充父项”的android按钮中的图标和文本居中

Posted

技术标签:

【中文标题】如何将宽度设置为“填充父项”的android按钮中的图标和文本居中【英文标题】:How to center icon and text in a android button with width set to "fill parent" 【发布时间】:2011-04-07 17:53:02 【问题描述】:

我想要一个带有图标+文本的 android Button。我正在使用 drawableLeft 属性来设置图像,如果按钮的宽度为"wrap_content",这很有效,但我需要拉伸到最大宽度,所以我使用宽度"fill_parent"。这会将我的图标直接移动到按钮的左侧,并且我希望图标和文本都在按钮内居中。

我已尝试设置填充,但这仅允许提供固定值,因此这不是我需要的。我需要在中心对齐图标+文本。

<Button 
    android:id="@+id/startTelemoteButton" 
    android:text="@string/start_telemote"
    android:drawableLeft="@drawable/start"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"            
    android:
    android:heigh="wrap_content" />

关于如何实现这一目标的任何建议?

【问题讨论】:

这可能没有简单的解决方案吗?我是否必须尝试使用​​带有图标的 9patch 按钮 img? 这可能是一个解决方案。按钮文本是本地化的还是静态的? 已本地化。没有其他解决方案吗?我设法用一个 9 补丁来做到这一点,但在更改语言环境时遇到了问题。 如何使用带有可绘制 TOP 的 Button 并为其添加一些填充? 糟糕的框架设计 【参考方案1】:

android:drawableLeft 始终保持 android:paddingLeft 与左边框的距离。当按钮没有设置为android:时,它会一直挂在左边!

在 Android 4.0(API 级别 14)中,您可以使用 android:drawableStart 属性在文本开头放置一个可绘制对象。我想出的唯一向后兼容的解决方案是使用 ImageSpan 创建 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);

在我的情况下,我还需要调整 Button 的 android:gravity 属性以使其看起来居中:

<Button
  android:id="@+id/button"
  android:layout_
  android:layout_
  android:minHeight="32dp"
  android:minWidth="150dp"
  android:gravity="center_horizontal|top" />

【讨论】:

不错。最后一行应该是button.setText(buttonLabel) Unicode 有大量与 Android 中的字符串兼容的字符图标。如果你能找到一个可以接受的解决方案,这是一个简单的解决方案,而且它还有一个额外的好处,那就是它会随文本大小缩放。例如,它有一个用于电子邮件图标的信封和几个不同的电话作为呼叫按钮。 我很困惑这对任何人来说是如何工作的,对我来说它绘制了 2 个图标......一个向左,一个直接在中心显示在文本顶部。 drawableStart 不起作用。请参阅此线程:***.com/questions/15350990/… 另外,似乎当您使用 spannable 设置文本时,样式会被忽略。 drawableStart 不起作用,在 API 级别 17 中添加以支持 rtl【参考方案2】:

之前所有的答案似乎都已经过时了

您现在可以使用MaterialButton 来设置图标的重力。

 <com.google.android.material.button.MaterialButton
        android:id="@+id/btnDownloadPdf"
        android:layout_
        android:layout_
        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" />

为了使用材料组件,您显然需要:

添加依赖 implementation 'com.google.android.material:material:1.3.0-alpha01'(使用最新版本)

让您的主题扩展 Material Components 主题

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
...
</style>

如果您不能这样做,请从 Material Bridge 主题扩展它

<style name="AppTheme" parent="Theme.MaterialComponents.Light.Bridge">
...
</style>

【讨论】:

谢谢!你救了我的一天!工作正常 不必更改整个应用程序主题,您可以通过在 MaterialButton 标签上使用 app:theme 只为按钮本身应用主题【参考方案3】:

我知道我回答这个问题迟了,但这对我有帮助:

<FrameLayout
            android:layout_
            android:layout_
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:background="@color/fb" >

            <Button
                android:id="@+id/fbLogin"
                android:layout_
                android:layout_
                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>

我从这里找到了这个解决方案:Android UI struggles: making a button with centered text and icon

【讨论】:

这样的问题是按钮不是框架布局的宽度。【参考方案4】:

我使用 LinearLayout 而不是 Button。我需要使用的 OnClickListener 也适用于 LinearLayout。

<LinearLayout
    android:id="@+id/my_button"
    android:layout_
    android:layout_
    android:background="@drawable/selector"
    android:gravity="center"
    android:orientation="horizontal"
    android:clickable="true">

    <ImageView
        android:layout_
        android:layout_
        android:layout_marginRight="15dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/icon" />

    <TextView
        android:layout_
        android:layout_
        android:gravity="center"
        android:text="Text" />

</LinearLayout>

【讨论】:

【参考方案5】:

我通过左右添加padding来调整如下:

<Button
            android:layout_
            android:layout_
            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"
            />

【讨论】:

paddingLeft 和 paddingRight 帮助了我的居中。为简单的解决方案投票。 如何处理宽度是动态的这一事实?如果旋转屏幕,所有图标都不会居中吗?我实际上正面临这个问题 这是最好的答案!【参考方案6】:

我最近遇到了同样的问题。试图找到一个更便宜的解决方案,所以想出了这个。

   <LinearLayout
        android:id="@+id/linearButton"
        android:layout_
        android:layout_
        android:background="@drawable/selector_button_translucent_ab_color"
        android:clickable="true"
        android:descendantFocusability="blocksDescendants"
        android:gravity="center"
        android:orientation="horizontal" >

        <ImageView
            android:layout_
            android:layout_
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:layout_
            android:layout_
            android:text="@string/app_name"
            android:textColor="@android:color/white" />
    </LinearLayout>

然后只需在LinearLayout 上拨打OnClickListener

希望这对某人有所帮助,因为这似乎是一个非常常见的问题。 :)

【讨论】:

这是一个好主意,但却是一个糟糕的解决方案。您可以使用 drawableLeft 属性仅使用一个 TextView 来实现相同的目的。这使您可以查看文本左侧的可绘制对象。 @muetzenflo 是的,没错。但是,当您使 textView 与父宽度匹配时,即使您将文本居中,您的可绘制对象也会移动到最左侧。如果我错了,请告诉我。问题只是关于这个。 啊抱歉..我来这里就是为了这个问题,在尝试了太多东西后失去了注意力:) 猜猜我只见树木不见森林。我的错!【参考方案7】:

您可以使用自定义按钮来测量和绘制自身以适应左侧可绘制对象。请查找示例和用法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);


用法

<com.mypackage.DrawableAlignedButton
        android:layout_
        android:layout_
        android:layout_weight="1"
        android:drawableLeft="@drawable/my_drawable"
        android:gravity="center"
        android:padding="7dp"
        android:text="My Text" />

【讨论】:

您可以在答案中包含代码,这应该是首选方式(如果不是太长的话),因为链接可能会随着时间的推移而失效- 不是很准确,但我接受了 它向右移动文本,但不够(图像与文本重叠)。此外,与其他自定义视图的解决方案一样,它不接受长文本。【参考方案8】:

这是我 3 年前写的解决方案。按钮有文本和左图标,并且在框架中,这里是实际的按钮,可以通过 fill_parent 进行拉伸。我无法再次测试它,但它当时正在工作。可能 Button 不必使用,可以用 TextView 代替,但我现在不会测试它,它不会在这里改变太多功能。

<FrameLayout
    android:id="@+id/login_button_login"
    android:background="@drawable/apptheme_btn_default_holo_dark"
    android:layout_
    android:layout_gravity="center"
    android:layout_>
    <Button
        android:clickable="false"
        android:drawablePadding="15dp"
        android:layout_gravity="center"
        style="@style/WhiteText.Small.Bold"
        android:drawableLeft="@drawable/lock"
        android:background="@color/transparent"
        android:text="LOGIN" />
</FrameLayout>

【讨论】:

现在我发现我并不孤单:)【参考方案9】:

我知道这个问题有点老了,但也许你仍然愿意接受提示或解决方法:

创建一个以按钮图像作为背景或按钮本身作为布局的第一个元素的RelativeLayout“wrap_content”。获取一个 LinearLayout 并将其设置为“layout_centerInParent”和“wrap_content”。然后将您的 Drawable 设置为 Imageview。最后用你的文本(语言环境)设置一个 TextView。

所以基本上你有这个结构:

RelativeLayout
  Button
    LinearLayout
      ImageView
      TextView

或者像这样:

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

我知道这个解决方案有很多元素需要处理,但是您可以使用它轻松创建自己的自定义按钮,还可以设置文本和绘图的确切位置:)

【讨论】:

这种方法可以很好地工作。就我而言,我只需要一个包含 TextView 的 RelativeLayout。 RelativeLayout 获得了背景,TextView 获得了 drawableLeft 图标。然后在代码中:如果需要,将 onClickListener 附加到 RelativeLayout 和 findViewById 分别为 TextView 第一个建议结构给出“Button cannot be cast to ViewGroup”异常。【参考方案10】:

我解决这个问题的方法是用轻量级的&lt;View ../&gt; 元素包围按钮,这些元素可以动态调整大小。下面是几个例子,说明可以用这个实现什么:

请注意,示例 3 中按钮的可点击区域与示例 2 中的相同(即带有空格),这与示例 4 中的按钮之间没有“不可点击”间隙不同。

代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical">
    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:layout_
        android:layout_
        android:textStyle="bold"
        android:text="Example 1: Button with a background color:"/>
    <LinearLayout
        android:layout_
        android:layout_>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="20dp"
            android:paddingEnd="20dp"
            android:layout_weight="0.3"/>
        <!-- Play around with the above 3 values to modify the clickable 
             area and image alignment with respect to text -->
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_
        android:layout_
        android:textStyle="bold"
        android:text="Example 2: Button group + transparent layout + spacers:"/>
    <LinearLayout
        android:layout_
        android:layout_>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_
        android:layout_
        android:textStyle="bold"
        android:text="Example 3: Button group + colored layout:"/>
    <LinearLayout
        android:layout_
        android:layout_
        android:background="@android:color/darker_gray">
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <View
            android:layout_
            android:layout_
            android:layout_weight="1"/>
    </LinearLayout>

    <TextView
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"
        android:layout_
        android:layout_
        android:textStyle="bold"
        android:text="Example 4 (reference): Button group + no spacers:"/>
    <LinearLayout
        android:layout_
        android:layout_
        android:background="@android:color/darker_gray">
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>
        <Button
            style="?android:attr/buttonBarButtonStyle"
            android:layout_
            android:layout_
            android:text="Button"
            android:textColor="@android:color/white"
            android:drawableLeft="@android:drawable/ic_secure"
            android:drawableStart="@android:drawable/ic_secure"
            android:background="@android:color/darker_gray"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:layout_weight="1"/>   
    </LinearLayout>
</LinearLayout>

【讨论】:

【参考方案11】:

尝试使用这个库

OmegaCenterIconButton

【讨论】:

【参考方案12】:

您可以创建自定义小部件:

Java 类 IButton:

public class IButton extends RelativeLayout 

private RelativeLayout layout;
private ImageView image;
private TextView text;

public IButton(Context context) 
    this(context, null);


public IButton(Context context, AttributeSet attrs) 
    this(context, attrs, 0);


public IButton(Context context, AttributeSet attrs, int defStyle) 
    super(context, attrs, defStyle);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.ibutton, this, true);

    layout = (RelativeLayout) view.findViewById(R.id.btn_layout);

    image = (ImageView) view.findViewById(R.id.btn_icon);
    text = (TextView) view.findViewById(R.id.btn_text);

    if (attrs != null) 
        TypedArray attributes = context.obtainStyledAttributes(attrs,R.styleable.IButtonStyle);

        Drawable drawable = attributes.getDrawable(R.styleable.IButtonStyle_button_icon);
        if(drawable != null) 
            image.setImageDrawable(drawable);
        

        String str = attributes.getString(R.styleable.IButtonStyle_button_text);
        text.setText(str);

        attributes.recycle();
    



@Override
public void setOnClickListener(final OnClickListener l) 
    super.setOnClickListener(l);
    layout.setOnClickListener(l);


public void setDrawable(int resId) 
    image.setImageResource(resId);

布局 ibutton.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/btn_layout"
android:layout_
android:layout_
android:clickable="true" >

<ImageView
    android:id="@+id/btn_icon"
    android:layout_
    android:layout_
    android:layout_marginRight="2dp"
    android:layout_toLeftOf="@+id/btn_text"
    android:duplicateParentState="true" />

<TextView
    android:id="@+id/btn_text"
    android:layout_
    android:layout_
    android:layout_centerInParent="true"
    android:duplicateParentState="true"
    android:gravity="center_vertical"
    android:textColor="#000000" />
</RelativeLayout>

为了使用这个自定义小部件:

<com.test.android.widgets.IButton
     android:id="@+id/new"
     android:layout_         
     android:layout_
     ibutton:button_text="@string/btn_new"
     ibutton:button_icon="@drawable/ic_action_new" />

您必须为自定义属性提供命名空间 xmlns:ibutton="http://schemas.android.com/apk/res/com.test.android.xxx" 其中 com.test.android.xxx 是应用的根包。

只要把它放在 xmlns:android="http://schemas.android.com/apk/res/android" 下面。

您最不需要的是 attrs.xml 中的自定义属性。

在 attrs.xml 中

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="IButtonStyle">
        <attr name="button_text" />
        <attr name="button_icon" format="integer" />
    </declare-styleable>

    <attr name="button_text" />

</resources>

为了更好的定位,如果您想避免RelativeLayout定位的潜在问题,请将自定义按钮包装在LinearLayout中。

享受吧!

【讨论】:

【参考方案13】:

有类似的问题,但希望有没有文本和没有包装布局的中心可绘制。解决方案是创建自定义按钮并在 LEFT、RIGHT、TOP、BOTTOM 之外再添加一个可绘制按钮。可以轻松地修改可绘制的位置并将其置于相对于文本的所需位置。

CenterDrawableButton.java

public class CenterDrawableButton extends Button 
    private Drawable mDrawableCenter;

    public CenterDrawableButton(Context context) 
        super(context);
        init(context, null);
    

    public CenterDrawableButton(Context context, AttributeSet attrs) 
        super(context, attrs);
        init(context, attrs);
    

    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr) 
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CenterDrawableButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    


    private void init(Context context, AttributeSet attrs)
        //if (isInEditMode()) return;
        if(attrs!=null)
            TypedArray a = context.getTheme().obtainStyledAttributes(
                    attrs, R.styleable.CenterDrawableButton, 0, 0);

            try 
                setCenterDrawable(a.getDrawable(R.styleable.CenterDrawableButton_drawableCenter));

             finally 
                a.recycle();
            

        
    

    public void setCenterDrawable(int center) 
        if(center==0)
            setCenterDrawable(null);
        else
        setCenterDrawable(getContext().getResources().getDrawable(center));
    
    public void setCenterDrawable(@Nullable Drawable center) 
        int[] state;
        state = getDrawableState();
        if (center != null) 
            center.setState(state);
            center.setBounds(0, 0, center.getIntrinsicWidth(), center.getIntrinsicHeight());
            center.setCallback(this);
        
        mDrawableCenter = center;
        invalidate();
        requestLayout();
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(mDrawableCenter!=null) 
            setMeasuredDimension(Math.max(getMeasuredWidth(), mDrawableCenter.getIntrinsicWidth()),
                    Math.max(getMeasuredHeight(), mDrawableCenter.getIntrinsicHeight()));
        
    
    @Override
    protected void drawableStateChanged() 
        super.drawableStateChanged();
        if (mDrawableCenter != null) 
            int[] state = getDrawableState();
            mDrawableCenter.setState(state);
            mDrawableCenter.setBounds(0, 0, mDrawableCenter.getIntrinsicWidth(),
                    mDrawableCenter.getIntrinsicHeight());
        
        invalidate();
    

    @Override
    protected void onDraw(@NonNull Canvas canvas) 
        super.onDraw(canvas);

        if (mDrawableCenter != null) 
            Rect rect = mDrawableCenter.getBounds();
            canvas.save();
            canvas.translate(getWidth() / 2 - rect.right / 2, getHeight() / 2 - rect.bottom / 2);
            mDrawableCenter.draw(canvas);
            canvas.restore();
        
    

attrs.xml

<resources>
    <attr name="drawableCenter" format="reference"/>
    <declare-styleable name="CenterDrawableButton">
        <attr name="drawableCenter"/>
    </declare-styleable>
</resources>

用法

<com.virtoos.android.view.custom.CenterDrawableButton
            android:id="@id/centerDrawableButton"
            android:layout_
            android:layout_
            app:drawableCenter="@android:drawable/ic_menu_info_details"/>

【讨论】:

谢谢!这就是我一直在寻找的。​​span> 你能帮我解决这个问题吗,***.com/questions/35912539/…,你的回答我非常接近它,但出现了两个可绘制对象 此解决方案将 drawable 放置在按钮的中心,就在居中的文本上方。【参考方案14】:

如果你尝试 android:gravity="center_horizo​​ntal" 会发生什么?

【讨论】:

它不起作用。文本有点居中,但 drawableLeft 粘在左侧。 太棒了。谢谢【参考方案15】:
<style name="captionOnly">
    <item name="android:background">@null</item>
    <item name="android:clickable">false</item>
    <item name="android:focusable">false</item>
    <item name="android:minHeight">0dp</item>
    <item name="android:minWidth">0dp</item>
</style>

<FrameLayout
   style="?android:attr/buttonStyle"
   android:layout_
   android:layout_ >

    <Button
       style="@style/captionOnly"
       android:layout_
       android:layout_
       android:layout_gravity="center"
       android:drawableLeft="@android:drawable/ic_delete"
       android:gravity="center"
       android:text="Button Challenge" />
</FrameLayout>

将 FrameLayout 放入 LinearLayout 并将方向设置为水平。

【讨论】:

【参考方案16】:

您可以将按钮放在 LinearLayout 上

<RelativeLayout
        android:layout_
        android:layout_
        android:background="@mipmap/bg_btn_fb">
        <LinearLayout
            android:layout_
            android:layout_
            android:gravity="center">
            <TextView
                android:layout_
                android:layout_
                android:id="@+id/lblLoginFb"
                android:textColor="@color/white"
                android:drawableLeft="@mipmap/icon_fb"
                android:textSize="@dimen/activity_login_fb_textSize"
                android:text="Login with Facebook"
                android:gravity="center" />
        </LinearLayout>
        <Button
            android:layout_
            android:layout_
            android:id="@+id/btnLoginFb"
            android:background="@color/transparent"
            />
    </RelativeLayout>

【讨论】:

【参考方案17】:

我认为 android:gravity="center" 应该可以工作

【讨论】:

对我不起作用。它使文本居中,但 drawableLeft 仍位于最左侧。 你必须在同一个父级下声明图标和文本,父级使用android:gravity = "centre"【参考方案18】:

正如 Rodja 所建议的,在 4.0 之前,没有直接的方法可以将文本与可绘制对象居中。实际上,设置 padding_left 值确实会将可绘制对象从边框移开。因此我的建议是,在运行时,您可以准确计算出您的可绘制对象需要从左边框有多少像素,然后使用setPadding 传递它 您的计算可能类似于

int paddingLeft = (button.getWidth() - drawableWidth - textWidth) / 2;

你的drawable的宽度是固定的,你可以查看它,你也可以计算或猜测文本的宽度。

最后,您需要将填充值乘以屏幕密度,您可以使用DisplayMetrics 来完成此操作

【讨论】:

【参考方案19】:

公共类 DrawableCenterTextView 扩展 TextView

public DrawableCenterTextView(Context context, AttributeSet attrs,
        int defStyle) 
    super(context, attrs, defStyle);


public DrawableCenterTextView(Context context, AttributeSet attrs) 
    super(context, attrs);


public DrawableCenterTextView(Context context) 
    super(context);


@Override
protected void onDraw(Canvas canvas) 
    Drawable[] drawables = getCompoundDrawables();
    if (drawables != null) 
        Drawable drawableLeft = drawables[0];
        Drawable drawableRight = drawables[2];
        if (drawableLeft != null || drawableRight != null) 
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            if (drawableLeft != null)
                drawableWidth = drawableLeft.getIntrinsicWidth();
            else if (drawableRight != null) 
                drawableWidth = drawableRight.getIntrinsicWidth();
            
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        
    
    super.onDraw(canvas);

【讨论】:

这对我根本不起作用。你能举个例子吗?也许我没有正确使用它【参考方案20】:

脏修复。

android:paddingTop="10dp"
android:drawableTop="@drawable/ic_src"

计算正确的填充解决了目的。但是,对于不同的屏幕,使用不同的填充并将其放在相应值文件夹中的维度资源中。

【讨论】:

【参考方案21】:

使用 RelativeLayout(容器)和 android:layout_centerHorizo​​ntal="true" ,我的样本:

                <RelativeLayout
                    android:layout_
                    android:layout_
                    android:layout_weight="1" >

                    <CheckBox
                        android:layout_
                        android:layout_
                        android:layout_centerHorizontal="true"
                        android:layout_gravity="center"
                        android:layout_marginBottom="5dp"
                        android:layout_marginLeft="10dp"
                        android:layout_marginTop="5dp"
                        android:button="@drawable/bg_fav_detail"
                        android:drawablePadding="5dp"
                        android:text=" Favorite" />
                </RelativeLayout>

【讨论】:

【参考方案22】:

保留按钮主题的其他可能性。

<Button
            android:id="@+id/pf_bt_edit"
            android:layout_
            android:layout_
            />

        <LinearLayout
            android:layout_
            android:layout_
            android:layout_alignBottom="@id/pf_bt_edit"
            android:layout_alignLeft="@id/pf_bt_edit"
            android:layout_alignRight="@id/pf_bt_edit"
            android:layout_alignTop="@id/pf_bt_edit"
            android:layout_margin="@dimen/margin_10"
            android:clickable="false"
            android:elevation="20dp"
            android:gravity="center"
            android:orientation="horizontal"
            >

            <ImageView
                android:layout_
                android:layout_
                android:adjustViewBounds="true"
                android:clickable="false"
                android:src="@drawable/ic_edit_white_48dp"/>

            <TextView
                android:id="@+id/pf_tv_edit"
                android:layout_
                android:layout_
                android:layout_marginLeft="@dimen/margin_5"
                android:clickable="false"
                android:gravity="center"
                android:text="@string/pf_bt_edit"/>

        </LinearLayout>

如果您添加了这个解决方案 @color/你的颜色 @color/your_highlight_color 在您的活动主题中,您可以在 Lollipop 上使用带有阴影和波纹的 Matherial 主题,而对于以前版本的扁平按钮,您可以在按下它时使用您的颜色和高亮坐标。

此外,使用此解决方案自动调整图片大小

结果: 首先在棒棒糖设备上 第二:在棒棒糖设备上 3th : Pre lollipop device press button

【讨论】:

【参考方案23】:

我使用paddingLefttextView 与图标居中,并将textView 与left|centerVertical 对齐。对于视图和图标之间的小间隙,我使用了drawablePadding

         <Button
            android:id="@+id/have_it_main"
            android:layout_
            android:layout_
            android:background="@drawable/textbox"
            android:drawableLeft="@drawable/have_it"
            android:drawablePadding="30dp"
            android:gravity="left|center_vertical"
            android:paddingLeft="60dp"
            android:text="Owner Contact"
            android:textColor="@android:color/white" />

【讨论】:

这不适用于许多屏幕,仅适用于 android:paddingLeft 工作的屏幕。【参考方案24】:

这可能是一个旧的/关闭的线程,但我到处搜索都没有找到有用的东西,直到我决定创建自己的解决方案。如果这里有人试图寻找答案,试试这个,可能会节省你一分钟的思考时间

          <LinearLayout
            android:id="@+id/llContainer"
            android:layout_
            android:layout_
            android:background="@drawable/selector"
            android:clickable="true"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="10dp"
            android:textStyle="bold">

            <TextView
                android:layout_
                android:layout_
                android:gravity="center"
                android:text="This is a text" />

            <ImageView
                android:layout_
                android:layout_
                android:src="@drawable/icon_image />


        </LinearLayout>

因为线性布局充当容器并且拥有选择器,所以当您单击整个线性布局时,它看起来就是它应该的样子。如果您希望它都居中,请使用相对 insteaf。如果您希望它水平居中,请将方向更改为水平。

请注意不要忘记将 android:clickable="true" 添加到您的主容器(相对或线性)以执行操作。

同样,这可能是旧线程,但仍然可以帮助那里的人。

-干杯希望它有所帮助- 快乐编码。

【讨论】:

【参考方案25】:

如果您使用自定义视图的解决方案之一,请小心,因为它们经常在长或多行文本上失败。我重写了一些答案,替换了onDraw() 并理解这是错误的方式。

【讨论】:

【参考方案26】:

我已经看到了在开始/左侧对齐可绘制对象的解决方案,但对于可绘制对象结束/右侧却没有,所以我想出了这个解决方案。它使用动态计算的填充来对齐左右两侧的可绘制对象和文本。

class IconButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.buttonStyle
) : AppCompatButton(context, attrs, defStyle) 

    init 
        maxLines = 1
    

    override fun onDraw(canvas: Canvas) 
        val buttonContentWidth = (width - paddingLeft - paddingRight).toFloat()

        val textWidth = paint.measureText(text.toString())

        val drawable = compoundDrawables[0] ?: compoundDrawables[2]
        val drawableWidth = drawable?.intrinsicWidth ?: 0
        val drawablePadding = if (textWidth > 0 && drawable != null) compoundDrawablePadding else 0
        val bodyWidth = textWidth + drawableWidth.toFloat() + drawablePadding.toFloat()

        canvas.save()

        val padding = (buttonContentWidth - bodyWidth).toInt() / 2
        val leftOrRight = if (compoundDrawables[0] != null) 1 else -1
        setPadding(leftOrRight * padding, 0, -leftOrRight * padding, 0)

        super.onDraw(canvas)
        canvas.restore()
    

根据您在哪里设置图标,将布局中的重力设置为“center_vertical|start”或“center_vertical|end”非常重要。例如:

<com.***.util.IconButton
        android:id="@+id/cancel_btn"
        android:layout_
        android:layout_
        android:layout_weight="1"
        android:drawableStart="@drawable/cancel"
        android:drawablePadding="@dimen/padding_small"
        android:gravity="center_vertical|start"
        android:text="Cancel" />

这个实现的唯一问题是按钮只能有单行文本,否则文本区域会填充按钮并且填充将为0。

【讨论】:

【参考方案27】:

试试这个你会找到你要找的,

 <Button
   android:id="@+id/button_my_profile"
   style="@style/whiteTextBlackButtonStyle.size18"
   android:layout_
   android:layout_weight="1"
   android:layout_
   android:gravity="center"
   android:drawableTop="@drawable/ic_more_profile"
   android:drawablePadding="8dp"
   android:paddingStart="16dp"
   android:text="@string/title_my_profile"
   android:textAllCaps="false"
   tools:layout_editor_absoluteY="24dp" />

【讨论】:

【参考方案28】:

考虑ImageButton

android:src 属性可用于设置在 Button 中居中的可绘制对象。

<ImageButton
    android:src="@drawable/your_drawable"
    ...
/>

【讨论】:

【参考方案29】:

使用这个 android:background="@drawable/ic_play_arrow_black_24dp"

只需将背景设置为要居中的图标

【讨论】:

以上是关于如何将宽度设置为“填充父项”的android按钮中的图标和文本居中的主要内容,如果未能解决你的问题,请参考以下文章

Android:根据宽度在 XML 中设置按钮高度

如何拉伸 TreeViewItem 宽度以填充父项?

Android - 获取设置为 wrap_content 的按钮的宽度

Android:如何设置AlertDialog的宽度和高度,以及AlertDialog风格的按钮?

在 Android 中如何获取设置为 Wrap_Content 的 Textview 的宽度

Android相对布局与按钮宽度使用权重