Android-CheckBox和文本之间的间距


256

是否有一种简单的方法可以在CheckBox控件的复选框和关联的文本之间添加填充?

我不能只添加前导空格,因为我的标签是多行的。

照原样,文本离复选框太近了: 替代文字


1
一个简单的解决方案是使用TextViewwith drawableLeft和use drawablePadding为文本提供空间。在代码中,只需切换选中状态和未选中状态即可。
穆罕默德·巴巴尔

我刚刚注意到一个名为android:drawablePadding的新xml属性,该属性应该设置可绘制对象和文本之间的间距。我没有尝试过,但我认为这是Google针对此问题的“事后”解决方案。
佩里·哈特曼

Answers:


333

我不想回答自己的问题,但是在这种情况下,我认为我需要回答。检查完后,@ Falmarri的答案正确无误。问题在于,Android的CheckBox控件已使用android:paddingLeft属性获取其所在位置的文本。

红线显示整个CheckBox的paddingLeft偏移值

替代文字

如果我只是在XML布局中覆盖该填充,它将使布局混乱。以下是paddingLeft =“ 0”的设置:

替代文字

事实证明您无法用XML修复此问题。您已经在代码中做到了。这是我的代码片段,其硬编码填充增加了10dp。

final float scale = this.getResources().getDisplayMetrics().density;
checkBox.setPadding(checkBox.getPaddingLeft() + (int)(10.0f * scale + 0.5f),
        checkBox.getPaddingTop(),
        checkBox.getPaddingRight(),
        checkBox.getPaddingBottom());

这将为您提供以下内容,其中绿线是填充的增加。这比对值进行硬编码更为安全,因为不同的设备可能为复选框使用不同的可绘制对象。

替代文字

更新-正如人们最近在下面的答案中提到的那样,这种现象在Jelly Bean(4.2)中显然已经改变。您的应用将需要检查其运行在哪个版本上,并使用适当的方法。

对于4.3及更高版本,只需设置padding_left。有关详细信息,请参见htafoya的答案。


108
回答自己的问题没错-将来其他人可能会遇到这个问题,而您只是给出了一个很好而全面的答案。
AndrewKS,2010年

4
仅仅设置有什么问题paddingLeft="48sp"?即使我更改比例和方向,在这里也能正常工作。您的代码使我在项目列表上的填充值不稳定。
哈波

5
@harpo-您不能保证不同的设备制造商不会为复选框使用不同的图形,这意味着您的硬编码填充可能会破坏您在不同设备上的视觉布局。由于我正在阅读当前的填充并将其添加到页面上,这不会有问题,但是您必须确保只执行一次。
DougW

2
@Blundell-不一定。Android的开源。设备供应商可以用完全不同的尺寸替换完全不同的图形。他们出于某种原因喜欢做这样的事情。
DougW 2011年

2
不幸的是,您不能在getView()自定义适配器中使用此解决方案(如果您回收视图),因为填充会不断增加。要解决此问题,我必须使用以下方法:boolean isHackNeeded = Build.VERSION.SDK_INT < 17; float scale = context.getResources().getDisplayMetrics().density; if (isHackNeeded) {CheckBox rb = new CheckBox(context); this.PADDING = rb.getPaddingLeft() + Math.round(10.0f * scale); } else { this.PADDING = Math.round(10.0f * scale); }。然后将PADDING我使用的每个CheckBox都使用:check.setPadding(PADDING, check.getPaddingTop() ...
Alex Semeniuk

133

鉴于@DougW的响应,我管理版本的操作更加简单,我将其添加到复选框视图中:

android:paddingLeft="@dimen/padding_checkbox"

在两个值文件夹中找到尺寸的位置:

价值观

<resources>

    <dimen name="padding_checkbox">0dp</dimen>

</resources>

values-v17(4.2 JellyBean)

<resources>

    <dimen name="padding_checkbox">10dp</dimen>

</resources>

我有一个自定义检查项,请使用dps进行最佳选择。


2
到目前为止,这是最好的答案。虽然,实际上应该是values-v17因为该修复程序是在API 17中引入的(根据上述某些帖子)
icecreamman 2014年

一个完美的答案,仅对于较旧的api(值/维度),我将padding_checkbox设置为0dip(在API 10上保证金已经很大),对于value-v17 10dip,如htafoya建议。
2016年

70

使用属性android:drawableLeft而不是android:button。为了在可绘制和文本之间设置填充,请使用android:drawablePadding。定位可绘制用途android:paddingLeft

<CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:button="@null"
        android:drawableLeft="@drawable/check_selector"
        android:drawablePadding="-50dp"
        android:paddingLeft="40dp"
        />

结果


1
嗨,这是一个不错的方法,但是请注意,您会获得复选框默认图像的额外左边界bcoz ..
对此的

4
设置android:background="@android:color/transparent"和左边距将消失
madeuz

2
上面的代码非常适合我的单选按钮,并且在4.2 OS边界上保持一致。谢谢!
gnichola 2013年

1
这应该排名更高。正如@gnichola所说,这适用于Android版本,是一个非常干净的解决方案。创建一个样式并按如下所示在您的主题中进行分配: <item name="android:checkboxStyle">@style/CheckBox</item> 这样,您就定义了一次样式,并且仅引用一次。
Rosomack 2014年

1
还要将background设置为null(或自定义),否则lollipop +会获得包含整个视图的巨大圆圈波纹效果。您可以使用可利用<ripple>标记绘制的v21按钮来重新插入更合适的波纹
Tom

34

Android 4.2 Jelly Bean(API 17)从buttonDrawable(int的右边缘)放置文本paddingLeft。它也适用于RTL模式。

在4.2之前paddingLeft忽略buttonDrawable-它是从CompoundButton视图的左边缘获取的。

您可以通过XML解决-在旧版Android上将paddingLeft设置为buttonDrawable.width + requiredSpace。仅在API 17上将其设置为requiredSpace。例如,使用维度资源并在values-v17资源文件夹中覆盖。

该更改是通过android.widget.CompoundButton.getCompoundPaddingLeft();引入的;


4
这是这里唯一正确的答案-它可以指出问题并提供简单的解决方案,我已经在多个商业应用程序中成功使用了这些解决方案。
madej 2014年

1
如何获取XML中的buttonDrawable.width或对其进行硬编码?
贾里德·凯尔斯

1
我设法通过删除来解决了旧代码中的问题android:background="@android:color/transparent"
塞贝克2014年

公认的答案很好并且可行,但是这个答案简单有效。这应该被接受。
Reaz Murshed

27

是的,您可以通过添加填充来添加填充。

android:padding=5dp


4
这实际上有效。对于其中一个,仅需要paddingLeft,而不需要所有padding。但是,似乎paddingLeft已设置为40dp左右的值。如果将其设置为> 40dp,它将移开;如果将其设置为<40dp,它将在复选框下方移动。我将其标记为正确并提出另一个问题,因为我对此表示担忧。
DougW

好吧,我不知道你的布局不知道。
法尔马里(Falmarri)2010年

是的,不工作..特别是三星设备我遇到了问题。
Ranjith Kumar

1
通过添加填充来添加填充听起来很合理!
塞米利翁

21

如果您想要没有代码的简洁设计,请使用:

<CheckBox
   android:id="@+id/checkBox1"
   android:layout_height="wrap_content"
   android:layout_width="wrap_content"
   android:drawableLeft="@android:color/transparent"
   android:drawablePadding="10dp"
   android:text="CheckBox"/>

诀窍是将的颜色设置为透明,android:drawableLeft并为分配一个值android:drawablePadding。此外,透明度还允许您在任何背景颜色上使用此技术,而不会产生副作用-例如颜色不匹配。


16

API 17及更高版本,您可以使用:

android:paddingStart =“ 24dp”

API 16及以下版本,您可以使用:

android:paddingLeft =“ 24dp”


1
很好的答案。我无法想象填充将如何在复选框和文本之间提供空间。通常,“ Padding Left”是指组件的左侧。
穆罕默德·易卜拉欣



10

我不认识,但我测试了

<CheckBox android:paddingLeft="8mm" 并且仅将文本移到右侧,而不是整个控件。

很适合我。


1
我最近没有尝试过,因此肯定有可能在特定设备或更新的Android OS版本上运行。但我强烈建议您在不同的设置上进行测试,因为在我问这个问题时,这肯定不起作用。
DougW 2011年

我看到这在2.3.3和4.2之间有所不同(不确定更改发生在何处)。
Nate

dp不是mm吗?
Chrispix

10

为什么不只是扩展Android CheckBox以获得更好的填充。这样,您不必每次使用CheckBox都必须在代码中对其进行修复,而只需使用固定的CheckBox。

首先扩展复选框:

package com.whatever;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.CheckBox;

/**
 * This extends the Android CheckBox to add some more padding so the text is not on top of the
 * CheckBox.
 */
public class CheckBoxWithPaddingFix extends CheckBox {

    public CheckBoxWithPaddingFix(Context context) {
        super(context);
    }

    public CheckBoxWithPaddingFix(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CheckBoxWithPaddingFix(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public int getCompoundPaddingLeft() {
        final float scale = this.getResources().getDisplayMetrics().density;
        return (super.getCompoundPaddingLeft() + (int) (10.0f * scale + 0.5f));
    }
}

在XML中第二个,而不是创建普通的CheckBox,创建扩展的

<com.whatever.CheckBoxWithPaddingFix
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello there" />

2
您应该添加一个“ if”,以避免在OS> 4.2时执行此操作,因为在Jelly Bean中它们已“修复”此问题。
Martin Marconcini

1
实际上> = 4.2(17)。
Aleks N.

6

我刚刚得出以下结论:

如果您有一个自定义可绘制对象,请重写CheckBox并添加此方法:

@Override
public int getCompoundPaddingLeft() {

    // Workarround for version codes < Jelly bean 4.2
    // The system does not apply the same padding. Explantion:
    // http://stackoverflow.com/questions/4037795/android-spacing-between-checkbox-and-text/4038195#4038195

    int compoundPaddingLeft = super.getCompoundPaddingLeft();

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        Drawable drawable = getResources().getDrawable( YOUR CUSTOM DRAWABLE );
        return compoundPaddingLeft + (drawable != null ? drawable.getIntrinsicWidth() : 0);
    } else {
        return compoundPaddingLeft;
    }

}

如果使用系统可绘制对象,则为:

@Override
public int getCompoundPaddingLeft() {

    // Workarround for version codes < Jelly bean 4.2
    // The system does not apply the same padding. Explantion:
    // http://stackoverflow.com/questions/4037795/android-spacing-between-checkbox-and-text/4038195#4038195

    int compoundPaddingLeft = super.getCompoundPaddingLeft();

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        final float scale = this.getResources().getDisplayMetrics().density;
        return compoundPaddingLeft + (drawable != null ? (int)(10.0f * scale + 0.5f) : 0);
    } else {
        return compoundPaddingLeft;
    }

}

感谢你的回答 :)


4

在Jelly Bean中,此行为似乎已更改。paddingLeft技巧增加了额外的填充,使文本看起来过于偏右。还有人注意到吗?


感谢更新!我已经在回答中添加了注释。
DougW

4

对于复选标记和文本之间的空格,请使用:

android:paddingLeft="10dp"

但它会超过10dp,因为选中标记周围包含填充(大约5dp)。如果要删除填充,请参阅如何删除Android CheckBox周围的填充

android:paddingLeft="-5dp"
android:layout_marginStart="-5dp"
android:layout_marginLeft="-5dp"
// or android:translationX="-5dp" instead of layout_marginLeft

2
<CheckBox
        android:paddingRight="12dip" />

@AndrewKS-经过测试。不出所料,这会将填充添加到整个控件,而不是在复选框和文本之间。
DougW

您最好将文本放在单独的TextView中。
AndrewKS,2010年

@AndrewKS-关于可用性的坏主意。我希望用户能够触摸文本并选择/取消选择该复选框。它也破坏了许多可访问性功能,就像在网页中一样。
DougW

Bad idea for usability不,这不对。将复选框和文本视图都置于线性布局中,并使该线性布局可触摸。
Falmarri 2010年

1
-1这个答案没有解决问题中提出的问题,该问题与图像和文本之间的差距有关
David Laing

2

如果您具有复选框或单选按钮的自定义图像选择器,则必须设置相同的按钮和背景属性,例如:

            <CheckBox
                android:id="@+id/filter_checkbox_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:button="@drawable/selector_checkbox_filter"
                android:background="@drawable/selector_checkbox_filter" />

您可以使用背景属性控制复选框或单选按钮填充的大小。


不,您不必这样做。如果您的自定义背景与复选框/单选按钮标志符号不同,则这是不可接受的。
andr

2

只需要在xml文件中有一个参数

android:paddingLeft="20dp"

2

0dp在Android 9 API 28上,将minHeight和minWidth设置为最干净,最直接的解决方案:

<CheckBox
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="0dp"
        android:minWidth="0dp" />


1

我所做的是在(Relative)内部有TextView和。该显示器,我希望用户看到和文字没有任何文字。这样,我可以在所需位置设置位置/填充。CheckBoxLayoutTextViewCheckBoxCheckBox


1

我在Galaxy S3 mini(android 4.1.2)上遇到了同样的问题,我只是使自定义复选框扩展了AppCompatCheckBox 而不是CheckBox。现在,它可以完美运行了。


0

您需要获取要使用的图像的大小,以便将填充添加到该大小。在Android内部,它们会获得您在src上指定的可绘制对象,然后使用其大小。由于它是一个私有变量,没有getter,因此您无法访问它。另外,您无法获取com.android.internal.R.styleable.CompoundButton并从此处获取可绘制对象。

因此,您需要创建自己的样式(即custom_src),也可以直接在RadioButton的实现中添加它:

public class CustomRadioButton extends RadioButton {

    private Drawable mButtonDrawable = null;

    public CustomRadioButton(Context context) {
        this(context, null);
    }

    public CustomRadioButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomRadioButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mButtonDrawable = context.getResources().getDrawable(R.drawable.rbtn_green);
        setButtonDrawable(mButtonDrawable);
    }

    @Override
    public int getCompoundPaddingLeft() {
        if (Util.getAPILevel() <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            if (drawable != null) {
                paddingLeft += drawable.getIntrinsicWidth();
            }
        }
        return paddingLeft;
    }
}

0

由于您可能为android:button属性使用了drawable选择器,因此需要添加android:constantSize="true"和/或指定默认的drawable,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true">
  <item android:drawable="@drawable/check_on" android:state_checked="true"/>
  <item android:drawable="@drawable/check_off"/>
</selector>

之后,您需要android:paddingLeft在复选框xml中指定属性。

缺点:

在布局编辑器中,您将使文本位于api 16及以下版本的复选框下方,在这种情况下,您可以通过创建自定义复选框类(如建议的,但针对api级别16)来对其进行修复。

理由:

这是一个错误,因为StateListDrawable#getIntrinsicWidth()在内部使用了调用,CompoundButton但是< 0如果没有当前状态并且未使用常量大小,则可能会返回值。


0

克服此问题所需要做的就是添加android:singleLine="true"checkBoxandroid xml布局中:

<CheckBox 
   android:id="@+id/your_check_box"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:singleLine="true"
   android:background="@android:color/transparent"
   android:text="@string/your_string"/>

并且不会以编程方式添加任何特殊内容。


0

当我从选择器中使用自己的可绘制对象时,复选框图像重叠,我已使用以下代码解决了此问题:

CheckBox cb = new CheckBox(mActivity);
cb.setText("Hi");
cb.setButtonDrawable(R.drawable.check_box_selector);
cb.setChecked(true);
cb.setPadding(cb.getPaddingLeft(), padding, padding, padding);

感谢Alex Semeniuk


0

我最终通过更改图像来解决这个问题。刚刚在png文件中添加了额外的透明背景。该解决方案在所有API上均表现出色。


0

也许到了很晚,但我已经创建了实用程序方法来管理此问题。

只需将此方法添加到您的工具中:

public static void setCheckBoxOffset(@NonNull  CheckBox checkBox, @DimenRes int offsetRes) {
    float offset = checkBox.getResources().getDimension(offsetRes);
    setCheckBoxOffsetPx(checkBox, offset);
}

public static void setCheckBoxOffsetPx(@NonNull CheckBox checkBox, float offsetInPx) {
    int leftPadding;
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
        leftPadding = checkBox.getPaddingLeft() + (int) (offsetInPx + 0.5f);
    } else {
        leftPadding = (int) (offsetInPx + 0.5f);
    }
    checkBox.setPadding(leftPadding,
            checkBox.getPaddingTop(),
            checkBox.getPaddingRight(),
            checkBox.getPaddingBottom());
}

像这样使用:

    ViewUtils.setCheckBoxOffset(mAgreeTerms, R.dimen.space_medium);

或像这样:

    // Be careful with this usage, because it sets padding in pixels, not in dp!
    ViewUtils.setCheckBoxOffsetPx(mAgreeTerms, 100f);

-1

我没有调整Checkbox的文本,而是做了以下事情,它对所有设备都有效。1)在XML中,将复选框和textview彼此相邻添加;保持一定距离。2)将复选框文本大小设置为0sp。3)在复选框旁边的文本视图中添加相关文本。


-3

<CheckBox android:drawablePadding="16dip" -绘图对象和文本之间的填充。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.