Android - Spacing between CheckBox and text
Asked Answered
A

32

292

Is there an easy way to add padding between the checkbox in a CheckBox control, and the associated text?

I cannot just add leading spaces, because my label is multi-line.

As-is, the text is way too close to the checkbox: alt text

Alvy answered 27/10, 2010 at 21:14 Comment(4)
A simple solution would be using a TextView with drawableLeft and use drawablePadding to give space to text. In code just toggle selected and unselected states.Incentive
I just noticed a new xml attribute called android:drawablePadding, which is supposed to set the spacing between the drawable and the text. I didn't try it but I think it's google's "after-the-fact" fix for this problem.Tensile
https://mcmap.net/q/100134/-android-spacing-between-checkbox-and-textCube
Using only 'android:padding="10dp"' worked for me.Chuckle
A
355

I hate to answer my own question, but in this case I think I need to. After checking it out, @Falmarri was on the right track with his answer. The problem is that Android's CheckBox control already uses the android:paddingLeft property to get the text where it is.

The red line shows the paddingLeft offset value of the entire CheckBox

alt text

If I just override that padding in my XML layout, it messes up the layout. Here's what setting paddingLeft="0" does:

alt text

Turns out you can't fix this in XML. You have do it in code. Here's my snippet with a hardcoded padding increase of 10dp.

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

This gives you the following, where the green line is the increase in padding. This is safer than hardcoding a value, since different devices could use different drawables for the checkbox.

alt text

UPDATE - As people have recently mentioned in answers below, this behavior has apparently changed in Jelly Bean (4.2). Your app will need to check which version its running on, and use the appropriate method.

For 4.3+ it is simply setting padding_left. See htafoya's answer for details.

Alvy answered 27/10, 2010 at 22:20 Comment(13)
Nothing wrong with answering your own question - someone else will probably have this problem in the future and you just gave a good, comprehensive answer.Kingsize
What's wrong with just setting paddingLeft="48sp"? Works fine here, even if I change scale and orientation. Your code gave me erratic padding values over a list of items.Luigi
@Luigi - You have no guarantees that different device manufacturers won't use different graphics for the checkbox, meaning your hard-coded padding may break your visual layout on different devices. Since I'm reading the current padding and adding to it that won't be a problem, but you do have to make sure you only do it once.Alvy
@Alvy - but if they used a different graphic the android source would still be 45dip?Hypnoanalysis
@Hypnoanalysis - Not necessarily. Android's open source. A device vendor could substitute a totally different graphic with a totally different size. They love doing stuff like that for some reason.Alvy
awesome writeup for the solution! Instead of adding 0.5f I used the following equation: (int)Math.round(fCheckboxPaddingBeforeTextDIP * fScale)Dayledaylight
Unfortunately, you can't use this solution in getView() of custom Adapter (if you recycle your views), since padding will increase endlessly. To fix this problem I had to use something like this: 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); }. And then use PADDING for every CheckBox I inflate: check.setPadding(PADDING, check.getPaddingTop() ...Epirus
how to left pad the drawable?Gusher
One lesson: Don't just view in Jelly Bean after setting checkbox padding. Better yet, don't unconditionally set a checkbox's left padding.Puckett
Thanks for nice descriptive answer, but this is not working for me. I am getting proper text and checkbox in one device. While in another, text is overlapping the checkbox. And this code doesn't make any difference :(Pinetum
A tiny issue with the code: if it gets called repeatedly (e.g. onResume), the spacing goes awry. This is because checkBox.getPaddingLeft() retrieves the previously "corrected" spacing, then adds to it. In effect, repeated calls to the code gradually increase the spacing.Replevin
Hey what if I want to add padding to the left of the checkbox itself, and not between it and the text?Cadena
Simple solution would be this, you need to create a drawable for the button. <CheckBox android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/filter_item_background" android:button="@android:color/transparent" android:drawableLeft="@drawable/btn_check_square" //Create button in drawable android:drawablePadding="20dp" //Set space between Text & CB android:padding="5dp" android:textColor="@android:color/black" />Columbia
P
160

Given @DougW response, what I do to manage version is simpler, I add to my checkbox view:

android:paddingLeft="@dimen/padding_checkbox"

where the dimen is found in two values folders:

values

<resources>

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

</resources>

values-v17 (4.2 JellyBean)

<resources>

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

</resources>

I have a custom check, use the dps to your best choice.

Psalter answered 29/11, 2013 at 0:52 Comment(2)
This is the best answer so far. although, it should really be values-v17as the fix was introduced in API 17 (according to some posts above)Mulhouse
A perfect answer, just for older apis (values/dimens) I set padding_checkbox to 0dip (on API 10 margin is huge already) and for values-v17 10dip as htafoya suggested.Fivefinger
S
77

Use attribute android:drawableLeft instead of android:button. In order to set padding between drawable and text use android:drawablePadding. To position drawable use 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"
        />

result

Swick answered 18/12, 2012 at 13:52 Comment(5)
Hi , This is nice method but notice that u get extra left margin bcoz of the default image of checkbox .. any solutions for thatEuxenite
set android:background="@android:color/transparent" and left margin will dissapearHarmonic
The code above worked perfectly for my radio buttons, and is consistent across the 4.2 OS boundary. Thanks!Nacred
This should be ranked much higher. As @Nacred said, this works across Android versions and is quite a clean solution. Create a style and assign it in your theme like this : <item name="android:checkboxStyle">@style/CheckBox</item> That way, you have the style defined once and referenced once only.Complected
Also set background to null (or something custom), otherwise lollipop+ gets a massive circle ripple effect encompassing the entire view. You can use a v21 button drawable utilising the <ripple> tags for to put a more appropriate ripple back in.Nuzzle
M
34

Android 4.2 Jelly Bean (API 17) puts the text paddingLeft from the buttonDrawable (ints right edge). It also works for RTL mode.

Before 4.2 paddingLeft was ignoring the buttonDrawable - it was taken from the left edge of the CompoundButton view.

You can solve it via XML - set paddingLeft to buttonDrawable.width + requiredSpace on older androids. Set it to requiredSpace only on API 17 up. For example use dimension resources and override in values-v17 resource folder.

The change was introduced via android.widget.CompoundButton.getCompoundPaddingLeft();

Matsuyama answered 29/7, 2013 at 17:45 Comment(4)
It's the only correct answer here - it pinpoints the problem and provides simple solutions, which I've used successfully in multiple commercial apps.Cybill
How do you get buttonDrawable.width in XML or do you hard code it?Luciusluck
I managed to fix this issue in an old code by removing android:background="@android:color/transparent".Sheya
The accepted answer is nice and working, but this one is simple and effective. This should be accepted answer.Embellishment
M
33

Yes, you can add padding by adding padding.

android:padding=5dp

Muslim answered 27/10, 2010 at 21:15 Comment(5)
This actually works... sort of. For one, only paddingLeft is needed, not all padding. However, it looks like the paddingLeft is already set to a value of around 40dp. If I set it > 40dp it moves away, if I set it < 40dp it moves under the checkbox. I'm going to mark this as correct and open another question, because I have concerns about that.Alvy
Well I have no idea without seeing your layout.Muslim
yes not working..particularly samsung device I got problem.Siftings
Adding padding by adding padding sounds legit!Raggletaggle
plus one for saving my day @MuslimEncroach
R
24

If you want a clean design without codes, use:

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

The trick is to set colour to transparent for android:drawableLeft and assign a value for android:drawablePadding. Also, transparency allows you to use this technique on any background colour without the side effect - like colour mismatch.

Ranzini answered 6/10, 2013 at 18:9 Comment(0)
E
17

API 17 and above, you can use:

android:paddingStart="24dp"

API 16 and below, you can use:

android:paddingLeft="24dp"

Extrorse answered 31/1, 2016 at 4:12 Comment(1)
Very good answer. I can't imagine how the padding will give the space between check box and text. Usually Padding Left mean left of the component.Cube
E
16

In my case I solved this problem using this following CheckBox attribute in the XML:

*

android:paddingLeft="@dimen/activity_horizontal_margin"

*

Eade answered 23/2, 2016 at 8:16 Comment(1)
Very good answer. I can't imagine how the padding will give the space between check box and text. Usually Padding Left mean left of the component.Cube
I
15

Simple solution, add this line in the CheckBox properties, replace 10dp with your desired spacing value

android:paddingLeft="10dp"
Infallible answered 7/10, 2015 at 12:45 Comment(0)
T
11

I don't know guys, but I tested

<CheckBox android:paddingLeft="8mm" and only moves the text to the right, not entire control.

It suits me fine.

Transformation answered 12/9, 2011 at 12:54 Comment(3)
I haven't tried this recently, so it's certainly possible that this works on a specific device, or a newer Android OS version. I would highly recommend that you test on different setups though, because this definitely did not work at the time I asked this question.Alvy
I'm seeing this behave differently between 2.3.3 and 4.2 (not sure where in between the change occurred).Pricking
Do you mean dp not mm?Protonema
P
10

For space between the check mark and the text use:

android:paddingLeft="10dp"

But it becomes more than 10dp, because the check mark contains padding (about 5dp) around. If you want to remove padding, see How to remove padding around Android CheckBox:

android:paddingLeft="-5dp"
android:layout_marginStart="-5dp"
android:layout_marginLeft="-5dp"
// or android:translationX="-5dp" instead of layout_marginLeft
Presnell answered 21/11, 2019 at 15:43 Comment(6)
how to add padding at the end of text? Using margin_end makes the background not filled.Lacielacing
@HaiHack, does paddingRight work? I saw that it worked.Presnell
Sorry, I mean adding the space before the checkbox @PresnellLacielacing
@HaiHack, I see two options. 1) Extend CheckBox and do this programmatically. 2) Add FrameLayout over CheckBox with left padding.Presnell
please see my answer for better sollution @Presnell https://mcmap.net/q/100134/-android-spacing-between-checkbox-and-textLacielacing
@HaiHack, thank you! I remembered about this attribute, but thought it couldn't help. :)Presnell
B
9

Why not just extend the Android CheckBox to have better padding instead. That way instead of having to fix it in code every time you use the CheckBox you can just use the fixed CheckBox instead.

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

Second in your xml instead of creating a normal CheckBox create your extended one

<com.whatever.CheckBoxWithPaddingFix
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello there" />
Bleeding answered 14/6, 2012 at 21:40 Comment(2)
You should add an 'if' to avoid doing that if OS > 4.2 because in Jelly Bean they "fixed" this.Brittaniebrittany
Actually >= 4.2 (17).Dissipation
M
7

Setting minHeight and minWidth to 0dp was the cleanest and directest solution for me on Android 9 API 28:

<CheckBox
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="0dp"
        android:minWidth="0dp" />
Medorra answered 6/1, 2020 at 9:53 Comment(0)
T
6

I just concluded on this:

Override CheckBox and add this method if you have a custom drawable:

@Override
public int getCompoundPaddingLeft() {

    // Workarround for version codes < Jelly bean 4.2
    // The system does not apply the same padding. Explantion:
    // https://mcmap.net/q/100134/-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;
    }

}

or this if you use the system drawable:

@Override
public int getCompoundPaddingLeft() {

    // Workarround for version codes < Jelly bean 4.2
    // The system does not apply the same padding. Explantion:
    // https://mcmap.net/q/100134/-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;
    }

}

Thanks for the answer :)

Tunic answered 14/10, 2013 at 11:44 Comment(0)
S
5

only you need to have one parameter in xml file

android:paddingLeft="20dp"
Sidereal answered 22/12, 2015 at 9:18 Comment(2)
I believe you mean paddingStart ;)Wille
@ArtemMostyaev YesSidereal
M
4

This behavior appears to have changed in Jelly Bean. The paddingLeft trick adds additional padding, making the text look too far right. Any one else notice that?

Mollusc answered 12/1, 2013 at 22:45 Comment(1)
Thanks for the update! I've added a note to my answer about this.Alvy
K
2
<CheckBox
        android:paddingRight="12dip" />
Kingsize answered 27/10, 2010 at 21:17 Comment(7)
@Kingsize - Tested. As expected, this adds padding to the entire control, not in between the checkbox and the text.Alvy
You are probably better off having the text in a separate TextView.Kingsize
@Kingsize - Bad idea for usability. I want the user to be able to touch the text and select/deselect the checkbox. It also breaks many accessibility features, the same way as if you do that in a web page.Alvy
Bad idea for usability No it's not. Put both the checkbox and the textview in a linear layout and make that linearlayout touchable.Muslim
@Muslim - I mean yeah, I could do that, but then I'm basically re-implementing my own checkbox control. I'd just rather not do that.Alvy
-1 This answer doesn't address the issue posed in the question, which is about the gap between the image and the textCalcific
This answer was made at the time with the assumption that the checkbox and the text were in separate views.Kingsize
S
2

If you have custom image selector for checkbox or radiobutton you must set same button and background property such as this:

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

You can control size of checkbox or radio button padding with background property.

Sunnisunnite answered 24/1, 2013 at 12:39 Comment(1)
No, you do not have to do this. This is not acceptable if you have a custom background that's different from the checkbox/radiobutton glyph.Jer
C
2

I think this can help you

<CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:drawablePadding="-30dp"
        android:paddingLeft="30dp"
        android:drawableLeft="@drawable/check"
        />
Carboni answered 23/9, 2021 at 4:21 Comment(0)
S
2

if some one need padding around drawable try this

        <com.google.android.material.checkbox.MaterialCheckBox
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:button="@null"
        android:drawableStart="@drawable/button_selector"
        android:padding="@dimen/items_padding" />
Suwannee answered 1/11, 2021 at 11:26 Comment(0)
P
1

If you are creating custom buttons, e.g. see change look of checkbox tutorial

Then simply increase the width of btn_check_label_background.9.png by adding one or two more columns of transparent pixels in the center of the image; leave the 9-patch markers as they are.

Pleinair answered 26/10, 2011 at 15:21 Comment(0)
S
1

What I did, is having a TextView and a CheckBox inside a (Relative)Layout. The TextView displays the text that I want the user to see, and the CheckBox doesn't have any text. That way, I can set the position / padding of the CheckBox wherever I want.

Saintsimonianism answered 5/4, 2014 at 1:33 Comment(0)
T
1

I had the same problem with a Galaxy S3 mini (android 4.1.2) and I simply made my custom checkbox extend AppCompatCheckBox instead of CheckBox. Now it works perfectly.

Tentage answered 16/7, 2016 at 16:16 Comment(0)
L
1

@CoolMind has the nice way but it couldn't add the space at the beginning of checkbox by android:paddingLeft, instead use this way

<androidx.appcompat.widget.AppCompatCheckBox
                android:id="@+id/cbReason5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/white"
                android:button="@null"
                android:drawableStart="@drawable/custom_bg_checkbox"
                android:drawablePadding="8dp"
                android:paddingStart="16dp"
                android:paddingTop="12dp"
                android:paddingEnd="16dp"
                android:paddingBottom="12dp"
                android:text="Whatever"
                android:textColor="@color/textNormal"
                app:buttonCompat="@null" />

android:drawablePadding should help you

Lacielacing answered 28/7, 2021 at 8:20 Comment(0)
C
0

You need to get the size of the image that you are using in order to add your padding to this size. On the Android internals, they get the drawable you specify on src and use its size afterwards. Since it's a private variable and there are no getters you cannot access to it. Also you cannot get the com.android.internal.R.styleable.CompoundButton and get the drawable from there.

So you need to create your own styleable (i.e. custom_src) or you can add it directly in your implementation of the 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;
    }
}
Cony answered 13/2, 2014 at 17:21 Comment(0)
H
0

As you probably use a drawable selector for your android:button property you need to add android:constantSize="true" and/or specify a default drawable like this:

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

After that you need to specify android:paddingLeft attribute in your checkbox xml.

Cons:

In the layout editor you will the text going under the checkbox with api 16 and below, in that case you can fix it by creating you custom checkbox class like suggested but for api level 16.

Rationale:

it is a bug as StateListDrawable#getIntrinsicWidth() call is used internally in CompoundButton but it may return < 0 value if there is no current state and no constant size is used.

Hedvig answered 28/8, 2014 at 15:35 Comment(0)
K
0

All you have to do to overcome this problem is to add android:singleLine="true" to the checkBox in your android xml layout:

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

and nothing special will be added programmatically.

Kiser answered 10/5, 2015 at 21:6 Comment(0)
F
0

Checkbox image was overlapping when I used my own drawables from selector, I have solve this using below code :

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

Thanks to Alex Semeniuk

Foliole answered 16/6, 2015 at 10:25 Comment(0)
T
0

I end up with this issue by changing the images. Just added extra transparent background in png files. This solution works excellent on all the APIs.

Tomtom answered 22/4, 2016 at 11:58 Comment(0)
C
0

Maybe it is to late, but I've created utility methods to manage this issue.

Just add this methods to your utils:

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

And use like this:

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

or like this:

    // Be careful with this usage, because it sets padding in pixels, not in dp!
    ViewUtils.setCheckBoxOffsetPx(mAgreeTerms, 100f);
Ceratoid answered 24/5, 2016 at 12:20 Comment(0)
P
-1

Instead of adjusting the text for Checkbox, I have done following thing and it worked for me for all the devices. 1) In XML, add checkbox and a textview to adjacent to one after another; keeping some distance. 2) Set checkbox text size to 0sp. 3) Add relative text to that textview next to the checkbox.

Photomural answered 15/2, 2014 at 15:10 Comment(0)
G
-3

<CheckBox android:drawablePadding="16dip" - The padding between the drawables and the text.

Gwendolyngweneth answered 9/8, 2013 at 6:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.