Android - расстояние между CheckBox и текстом

256

Есть ли простой способ добавить отступ между флажком в элементе управления CheckBox и соответствующим текстом?

Я не могу просто добавить начальные пробелы, потому что мой ярлык многострочный.

Как есть, текст слишком близко к флажку: альтернативный текст

DougW
источник
1
Простое решение будет использовать TextViewс drawableLeftи использовать, drawablePaddingчтобы дать место для текста. В коде просто переключать выбранные и невыбранные состояния.
Мухаммед Бабар
Я только что заметил новый атрибут xml под названием android: drawablePadding, который должен устанавливать интервал между рисованным и текстом. Я не пробовал, но я думаю, что это Google исправил эту проблему.
Пери Хартман
stackoverflow.com/a/35572204/2219406
Мохамед Ибрагим

Ответы:

333

Ненавижу отвечать на свой вопрос, но в этом случае думаю, что мне нужно. После проверки @Falmarri был на правильном пути со своим ответом. Проблема в том, что элемент управления Android CheckBox уже использует свойство android: paddingLeft, чтобы получить текст, где он находится.

Красная линия показывает значение смещения paddingLeft всего CheckBox

альтернативный текст

Если я просто переопределяю это заполнение в моем макете 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 для деталей.

DougW
источник
108
Нет ничего плохого в ответе на ваш собственный вопрос - возможно, у кого-то еще будет эта проблема в будущем, и вы просто дали хороший, исчерпывающий ответ.
AndrewKS
4
Что не так с просто настройкой paddingLeft="48sp"? Здесь отлично работает, даже если я изменю масштаб и ориентацию. Ваш код дал мне ошибочные значения заполнения списка элементов.
Harpo
5
@harpo. У вас нет никаких гарантий, что разные производители устройств не будут использовать разную графику для этого флажка. Это означает, что жестко заданные отступы могут нарушить визуальный макет на разных устройствах. Так как я читаю текущий отступ и добавляю к нему, это не будет проблемой, но вы должны убедиться, что делаете это только один раз.
Дугв
2
@Blundell - Не обязательно. Android с открытым исходным кодом. Поставщик устройства может заменить совершенно другой рисунок совершенно другим размером. Они любят делать такие вещи по какой-то причине.
DougW
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() ...
Алекс Семенюк
133

Учитывая ответ @DougW, то, что я делаю для управления версией, проще, я добавляю к своему представлению флажка:

android:paddingLeft="@dimen/padding_checkbox"

где измерение находится в двух папках значений:

ценности

<resources>

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

</resources>

Значения-v17 (4,2 JellyBean)

<resources>

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

</resources>

У меня есть пользовательская проверка, используйте дпс на ваш лучший выбор.

htafoya
источник
2
Это лучший ответ на данный момент. хотя, это действительно должно быть так, values-v17как исправление было введено в API 17 (согласно некоторым постам выше)
icecreamman
Идеальный ответ, только для старых API (значений / размеров) я установил для padding_checkbox значение 0dip (в API 10 маржа уже огромна) и для значений -177 10dip, как предложил htafoya.
Яр
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 изображения по умолчанию флажка ... любые решения для этого
Code_Life
4
установленное android:background="@android:color/transparent"и левое поле исчезнет
Мадейз
2
Приведенный выше код отлично работает для моих переключателей и соответствует границам операционной системы 4.2. Спасибо!
Гникола
1
Это должно быть оценено намного выше. Как сказал @gnichola, это работает во всех версиях Android и является довольно чистым решением. Создайте стиль и назначьте его в своей теме следующим образом: <item name="android:checkboxStyle">@style/CheckBox</item> Таким образом, стиль определен один раз, а ссылка на него - только один раз.
Росомак
1
Также установите фоновое значение в null (или что-то нестандартное), в противном случае lollipop + получит эффект массивной круговой пульсации, охватывающий весь вид. Вы можете использовать кнопку v21, которую можно нарисовать, используя теги <ripple> для того, чтобы вернуть более подходящую рябь обратно.
Том
34

Android 4.2 Jelly Bean (API 17) помещает текст paddingLeft из buttonDrawable (отступает правый край). Это также работает для режима RTL.

До версии 4.2 paddingLeft игнорировал buttonDrawable - он был взят с левого края представления CompoundButton.

Вы можете решить это с помощью XML - установите paddingLeft в buttonDrawable.width + requiredSpace на старых андроидах. Установите его для requiredSpace только на API 17 и выше. Например, используйте ресурсы измерений и переопределите их в папке ресурсов values-v17.

Изменение было введено через android.widget.CompoundButton.getCompoundPaddingLeft ();

kotucz
источник
4
Это единственный правильный ответ - он точно определяет проблему и предлагает простые решения, которые я успешно использовал в нескольких коммерческих приложениях.
Мадей
1
Как вы получаете buttonDrawable.width в XML или вы жестко его код?
Джаред Келлс
1
Мне удалось исправить эту проблему в старом коде, удалив android:background="@android:color/transparent".
Себек
Принятый ответ хорош и работает, но этот простой и эффективный. Это должен быть принят ответ.
Реаз Муршед
27

Да, вы можете добавить отступы, добавив отступы.

android:padding=5dp

Falmarri
источник
4
Это на самом деле работает ... вроде. Для одного необходим только paddingLeft, а не весь padding. Тем не менее, похоже, что paddingLeft уже установлен на значение около 40dp. Если я установлю его> 40dp, он уйдет, если я установлю его <40dp, он переместится под флажок. Я собираюсь отметить это как правильный и открыть еще один вопрос, потому что у меня есть опасения по этому поводу.
DougW
Ну, я понятия не имею, не видя ваш макет.
Фалмарри
да не работает .. в частности самсунг устройство у меня проблемы.
Ранджит Кумар
1
Добавление отступов путем добавления звуков дополнения законно!
Sermilion
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. Кроме того, прозрачность позволяет использовать эту технику на любом цвете фона без побочных эффектов, таких как несоответствие цвета.

ChuongPham
источник
16

API 17 и выше, вы можете использовать:

андроид: paddingStart = "24dp"

API 16 и ниже, вы можете использовать:

андроид: paddingLeft = "24dp"

Inmer
источник
1
Очень хороший ответ Я не могу себе представить, как отступ будет давать пространство между флажком и текстом. Обычно отступ слева означает, что слева от компонента.
Мохамед Ибрагим
14

В моем случае я решил эту проблему, используя следующий атрибут CheckBox в XML:

*

андроид: paddingLeft = "@ DIMEN / activity_horizontal_margin"

*

Мохаммед Закария
источник
Очень хороший ответ Я не могу себе представить, как отступ будет давать пространство между флажком и текстом. Обычно отступ слева означает, что слева от компонента.
Мохамед Ибрагим
13

Простое решение, добавьте эту строку в свойствах CheckBox , замените 10dp на желаемое значение расстояния

android:paddingLeft="10dp"
Навид Ахмад
источник
10

Я не знаю, ребята, но я проверял

<CheckBox android:paddingLeft="8mm" и только перемещает текст вправо, а не весь контроль.

Меня это устраивает нормально.

Tiago
источник
1
Я не пробовал это в последнее время, поэтому вполне возможно, что это работает на конкретном устройстве или более новой версии Android OS. Я настоятельно рекомендую вам протестировать различные настройки, потому что это определенно не сработало, когда я задал этот вопрос.
DougW
Я вижу, что это ведет себя по-разному между 2.3.3 и 4.2 (не уверен, где между изменения произошли).
Nate
Вы имеете в виду дп не мм?
Chrispix
10

Почему бы просто не расширить Android CheckBox, чтобы улучшить заполнение. Таким образом, вместо того, чтобы фиксировать его в коде каждый раз, когда вы используете 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" />
w.donahue
источник
2
Вы должны добавить 'if', чтобы избежать этого, если OS> 4.2, потому что в Jelly Bean они "исправили" это.
Мартин Маркончини
1
На самом деле> = 4,2 (17).
Алекс Н.
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;
    }

}

или это если вы используете систему 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;
    }

}

Спасибо за ответ :)

PaNaVTEC
источник
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
CoolMind
источник
2
<CheckBox
        android:paddingRight="12dip" />
AndrewKS
источник
@AndrewKS - Проверено. Как и ожидалось, это добавляет заполнение ко всему элементу управления, а не между флажком и текстом.
DougW
Возможно, вам лучше иметь текст в отдельном TextView.
AndrewKS
@AndrewKS - Плохая идея для удобства использования. Я хочу, чтобы пользователь мог прикоснуться к тексту и установить / снять флажок. Это также нарушает многие функции доступности, так же, как если бы вы делали это на веб-странице.
DougW
Bad idea for usabilityНет, это не так. Поместите оба флажка и текстовое представление в линейное расположение и сделайте это линейное расположение доступным для восприятия.
Фалмарри
1
-1 Этот ответ не затрагивает проблему, поставленную в вопросе, которая касается разрыва между изображением и текстом
Дэвид Лэйнг,
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" />

Вы можете контролировать размер флажка или переключателя с помощью свойства background.

Илья Лисвей
источник
Нет, ты не обязан это делать. Это недопустимо, если у вас есть собственный фон, который отличается от глифа флажка / кнопки.
Андрей
2

только вам нужно иметь один параметр в XML-файле

android:paddingLeft="20dp"
тей шах
источник
2

Установка minHeight и minWidth на 0dpбыло самым чистым и прямым решением для меня на 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" />
ManuelTS
источник
1

Если вы создаете пользовательские кнопки, например, см. Изменение внешнего вида учебника по флажкам

Затем просто увеличьте ширину btn_check_label_background.9.png, добавив еще один или два столбца прозрачных пикселей в центре изображения; оставьте маркеры с 9 участками как есть.

Кит Бирдмор
источник
1

То, что я сделал, имеет TextViewи CheckBoxвнутри (родственник) Layout. На TextViewэкране отображается текст, который я хочу видеть пользователю, а CheckBoxтекст отсутствует. Таким образом, я могу установить положение / отступ там, CheckBoxгде я хочу.

mbmc
источник
1

У меня была такая же проблема с Galaxy S3 mini (android 4.1.2), и я просто сделал свой собственный флажок расширением AppCompatCheckBox вместо CheckBox. Теперь это работает отлично.

Квентин Г.
источник
0

Вам нужно получить размер изображения, которое вы используете, чтобы добавить ваш отступ к этому размеру. На внутренних устройствах Android они получают отрисовку, указанную вами в src, и впоследствии используют ее размер. Поскольку это закрытая переменная и нет получателей, вы не можете получить к ней доступ. Также вы не можете получить 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;
    }
}
hudomju
источник
0

Поскольку вы, вероятно, используете селектор drawable для вашего android:buttonсвойства, вам нужно добавить android:constantSize="true"и / или указать рисование по умолчанию, например:

<?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"к checkBoxвашему андроиду макета 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);

Спасибо Алексею Семенюку

Джайпракаш Сони
источник
0

Я заканчиваю с этой проблемой, изменяя изображения. Просто добавлен дополнительный прозрачный фон в png файлах. Это решение отлично работает на всех API.

Лев Droidcoder
источник
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 добавьте флажок и текстовое представление рядом друг с другом; сохраняя некоторое расстояние. 2) Установите размер текста флажка на 0sp. 3) Добавьте относительный текст в это текстовое поле рядом с флажком.

Панкадж Дешпанде
источник
-3

<CheckBox android:drawablePadding="16dip" - Обивка между рисованными объектами и текстом.

user1879118
источник