Android - Spacing between CheckBox and text
Is there a开发者_JAVA百科n 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:
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
If I just override that padding in my XML layout, it messes up the layout. Here's what setting paddingLeft="0" does:
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.
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.
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.
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"
/>
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();
Yes, you can add padding by adding padding.
android:padding=5dp
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.
API 17 and above, you can use:
android:paddingStart="24dp"
API 16 and below, you can use:
android:paddingLeft="24dp"
In my case I solved this problem using this following CheckBox attribute in the XML:
*
android:paddingLeft="@dimen/activity_horizontal_margin"
*
Simple solution, add this line in the CheckBox properties, replace 10dp with your desired spacing value
android:paddingLeft="10dp"
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.
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
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" />
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" />
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:
// 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;
}
}
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:
// 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;
}
}
Thanks for the answer :)
only you need to have one parameter in xml file
android:paddingLeft="20dp"
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?
<CheckBox
android:paddingRight="12dip" />
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.
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"
/>
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.
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.
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.
@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
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;
}
}
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.
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.
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
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.
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);
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" />
精彩评论