Android - Odstępy między CheckBox a tekstem


256

Czy istnieje prosty sposób na dodanie dopełnienia między polem wyboru w kontrolce CheckBox a powiązanym tekstem?

Nie mogę po prostu dodać wiodących spacji, ponieważ moja etykieta jest wielowierszowa.

Na obecnym etapie tekst jest zbyt blisko pola wyboru: alternatywny tekst


1
Prostym rozwiązaniem byłoby użycie za TextViewpomocą drawableLefti użycie, drawablePaddingaby zwolnić miejsce na tekst. W kodzie po prostu przełączaj wybrane i niezaznaczone stany.
Muhammad Babar

Właśnie zauważyłem nowy atrybut xml o nazwie android: drawablePadding, który ma ustawiać odstępy między rysowalnym a tekstem. Nie próbowałem tego, ale myślę, że to rozwiązanie „po fakcie” google dla tego problemu.
Peri Hartman,

Odpowiedzi:


333

Nienawidzę odpowiadać na własne pytanie, ale w tym przypadku myślę, że muszę. Po sprawdzeniu, @Falmarri był na dobrej drodze ze swoją odpowiedzią. Problem polega na tym, że kontrolka CheckBox systemu Android korzysta już z właściwości android: paddingLeft, aby uzyskać tekst tam, gdzie jest.

Czerwona linia pokazuje wartość przesunięcia paddingLeft dla całego CheckBox

alternatywny tekst

Jeśli po prostu zastąpię to wypełnienie w moim układzie XML, spowoduje to popsucie układu. Oto, co robi ustawienie paddingLeft = "0":

alternatywny tekst

Okazuje się, że nie można tego naprawić w XML. Zrobisz to w kodzie. Oto mój fragment kodu ze zwiększonym zakresem wypełnienia o 10dp.

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

To daje następujące, gdzie zielona linia to wzrost wypełnienia. Jest to bezpieczniejsze niż zapisywanie wartości na stałe, ponieważ różne urządzenia mogą używać różnych rysunków dla pola wyboru.

alternatywny tekst

AKTUALIZACJA - jak ludzie ostatnio wspomnieli w odpowiedziach poniżej, to zachowanie najwyraźniej zmieniło się w Jelly Bean (4.2). Twoja aplikacja będzie musiała sprawdzić, na której wersji jest uruchomiona, i użyć odpowiedniej metody.

W wersji 4.3+ jest to po prostu ustawienie padding_left. Szczegółowe informacje można znaleźć w odpowiedzi htafoya.


108
Nie ma nic złego w udzieleniu odpowiedzi na własne pytanie - ktoś inny prawdopodobnie będzie miał ten problem w przyszłości, a ty po prostu udzieliłeś dobrej, wyczerpującej odpowiedzi.
AndrewKS

4
Co jest nie tak z samym ustawieniem paddingLeft="48sp"? Działa tutaj dobrze, nawet jeśli zmienię skalę i orientację. Twój kod podał mi nieprawidłowe wartości wypełnienia na liście elementów.
harpo

5
@harpo - Nie masz gwarancji, że różni producenci urządzeń nie użyją innej grafiki dla pola wyboru, co oznacza, że ​​zakodowane na stałe wypełnienie może uszkodzić układ wizualny na różnych urządzeniach. Ponieważ czytam bieżące wypełnienie i dodawanie do niego, nie będzie to problemem, ale musisz upewnić się, że zrobisz to tylko raz.
DougW

2
@Blundell - niekoniecznie. Android open source. Sprzedawca urządzeń może zastąpić zupełnie inną grafikę całkowicie innym rozmiarem. Z jakiegoś powodu uwielbiają robić takie rzeczy.
DougW,

2
Niestety nie możesz użyć tego rozwiązania w getView()niestandardowym adapterze (jeśli przetworzysz swoje widoki), ponieważ wypełnienie będzie się zwiększać w nieskończoność. Aby rozwiązać ten problem, musiałem użyć coś takiego: 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); }. A następnie użyj PADDINGdla każdego napełnionego CheckBox:check.setPadding(PADDING, check.getPaddingTop() ...
Alex Semeniuk

133

Biorąc pod uwagę odpowiedź @DougW, co robię, aby zarządzać wersją, jest prostsze, dodaję do mojego pola wyboru:

android:paddingLeft="@dimen/padding_checkbox"

gdzie dimen znajduje się w dwóch folderach wartości:

wartości

<resources>

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

</resources>

wartości-v17 (4.2 JellyBean)

<resources>

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

</resources>

Mam niestandardowy czek, użyj dps do najlepszego wyboru.


2
To najlepsza jak dotąd odpowiedź. chociaż tak naprawdę powinno być values-v17tak, jak poprawka została wprowadzona w API 17 (zgodnie z niektórymi powyższymi postami)
lody

Idealna odpowiedź, tylko dla starszych apis (wartości / wymiary) ustawiłem padding_checkbox na 0dip (na API 10 margines jest już ogromny), a dla wartości-v17 10dip, jak sugeruje htafoya.
Yar

70

Użyj atrybutu android:drawableLeftzamiast android:button. Aby ustawić wypełnienie między rysowaniem a tekstem android:drawablePadding. Aby ustawić wysuwane użycie 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"
        />

wynik


1
Cześć, To miła metoda, ale zauważ, że dostaniesz dodatkowy lewy margines bcoz domyślnego obrazu pola wyboru .. wszelkie rozwiązania tego
Code_Life 23.01.2013

4
ustawiony android:background="@android:color/transparent"i lewy margines zniknie
madeuz

2
Powyższy kod działał idealnie dla moich przycisków opcji i jest spójny w granicach systemu operacyjnego 4.2. Dzięki!
gnichola

1
To powinno być ocenione znacznie wyżej. Jak powiedział @gnichola, działa to we wszystkich wersjach Androida i jest dość czystym rozwiązaniem. Utwórz styl i przypisz go do motywu w następujący <item name="android:checkboxStyle">@style/CheckBox</item> sposób : W ten sposób styl zostanie zdefiniowany tylko raz, a odniesienie do niego będzie możliwe tylko raz.
Rosomack

1
Ustaw także tło na null (lub coś niestandardowego), w przeciwnym razie Lollipop + uzyska efekt masywnego tętnienia koła obejmującego cały widok. Możesz użyć przycisku v21 do rysowania za pomocą tagów <ripple>, aby ponownie wprowadzić bardziej odpowiednie tętnienie.
Tom

34

Android 4.2 Jelly Bean (API 17) umieszcza tekst paddingLeft z przyciskuDrawable (ints prawa krawędź). Działa również w trybie RTL.

Przed 4.2 paddingLeft ignorował przyciskDrawable - został pobrany z lewej krawędzi widoku CompoundButton.

Możesz to rozwiązać za pomocą XML - ustaw paddingLeft na buttonDrawable.width + wymaganySpace na starszych androidach. Ustaw na wymagane Miejsce tylko w API 17 w górę. Na przykład użyj zasobów wymiarów i zastąp w folderze zasobów wartości-17.

Zmiana została wprowadzona za pośrednictwem android.widget.CompoundButton.getCompoundPaddingLeft ();


4
To jedyna poprawna odpowiedź tutaj - wskazuje problem i zapewnia proste rozwiązania, które z powodzeniem zastosowałem w wielu aplikacjach komercyjnych.
madej

1
Jak uzyskać buttonDrawable.width w XML lub kodujesz go na stałe?
Jared Kells

1
Usunąłem ten problem w starym kodzie android:background="@android:color/transparent".
Sebek

Przyjęta odpowiedź jest miła i działa, ale ta jest prosta i skuteczna. Należy zaakceptować odpowiedź.
Reaz Murshed

27

Tak, możesz dodać dopełnienie, dodając dopełnienie.

android:padding=5dp


4
To faktycznie działa ... tak jakby. Po pierwsze, potrzebna jest tylko paddingLeft, a nie cała padding. Wygląda jednak na to, że paddingLeft ma już wartość około 40dp. Jeśli ustawię> 40dp, odsunie się, jeśli ustawię <40dp, przesunie się pod polem wyboru. Oznaczę to jako poprawne i otworzę kolejne pytanie, ponieważ mam obawy.
DougW

Nie mam pojęcia, nie widząc twojego układu.
Falmarri

tak nie działa .. szczególnie urządzenie Samsung Mam problem.
Ranjith Kumar

1
Dodawanie dopełnienia przez dodanie dopełnienia brzmi legalnie!
Kazanie

21

Jeśli chcesz mieć czysty design bez kodów, użyj:

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

Sztuką jest ustawienie koloru na przezroczysty android:drawableLefti przypisanie wartości android:drawablePadding. Ponadto przezroczystość pozwala na użycie tej techniki na dowolnym kolorze tła bez efektu ubocznego - np. Niedopasowanie kolorów.


16

API 17 i wyżej, możesz użyć:

android: paddingStart = "24dp"

API 16 i poniżej, możesz użyć:

android: paddingLeft = "24dp"


1
Bardzo dobra odpowiedź. Nie mogę sobie wyobrazić, jak wypełnienie zapewni odstęp między polem wyboru a tekstem. Zwykle Padding Left oznacza lewą stronę elementu.
Mohamed Ibrahim

14

W moim przypadku rozwiązałem ten problem za pomocą następującego atrybutu CheckBox w pliku XML:

*

android: paddingLeft = "@ dimen / activity_horizontal_margin"

*


Bardzo dobra odpowiedź. Nie mogę sobie wyobrazić, jak wypełnienie zapewni odstęp między polem wyboru a tekstem. Zwykle Padding Left oznacza lewą stronę elementu.
Mohamed Ibrahim,

13

Proste rozwiązanie, dodaj ten wiersz do właściwości CheckBox , zastąp 10dp żądaną wartością odstępu

android:paddingLeft="10dp"

10

Nie znam facetów, ale testowałem

<CheckBox android:paddingLeft="8mm" i przesuwa tylko tekst w prawo, a nie całą kontrolę.

To mi odpowiada.


1
Nie próbowałem tego ostatnio, więc z pewnością możliwe jest, że działa to na określonym urządzeniu lub nowszej wersji systemu operacyjnego Android. Gorąco polecam przetestowanie różnych konfiguracji, ponieważ zdecydowanie nie działało to w chwili, gdy zadałem to pytanie.
DougW,

Widzę, że zachowuje się inaczej w wersjach 2.3.3 i 4.2 (nie jestem pewien, gdzie pomiędzy zmianami nastąpiła).
Nate

Masz na myśli dp nie mm?
Chrispix

10

Dlaczego nie po prostu rozszerzyć Android CheckBox, aby zamiast tego mieć lepszą wypełnienie. W ten sposób zamiast konieczności poprawiania go w kodzie za każdym razem, gdy używasz CheckBox, możesz zamiast tego użyć po prostu ustalonego CheckBox.

Najpierw rozszerz 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));
    }
}

Po drugie w swoim xml zamiast tworzenia normalnego CheckBox utwórz swój rozszerzony

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

2
Powinieneś dodać „if”, aby tego uniknąć, jeśli OS> 4.2, ponieważ w Jelly Bean „naprawili” to.
Martin Marconcini

1
W rzeczywistości> = 4,2 (17).
Aleks N.

6

Właśnie do tego doszedłem:

Zastąp CheckBox i dodaj tę metodę, jeśli masz niestandardowy program do rysowania:

@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;
    }

}

lub to, jeśli używasz systemu do rysowania:

@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;
    }

}

Dziękuję za odpowiedź :)


4

Wygląda na to, że to zachowanie zmieniło się w Jelly Bean. Sztuczka paddingLeft dodaje dodatkowe dopełnienie, dzięki czemu tekst wygląda zbyt daleko w prawo. Czy ktoś to zauważył?


Dziękuję za aktualizację! Do mojej odpowiedzi dodałem notatkę na ten temat.
DougW

4

Aby wstawić spację między znacznikiem wyboru a tekstem, użyj:

android:paddingLeft="10dp"

Ale staje się on większy niż 10dp, ponieważ znacznik wyboru zawiera dopełnienie (około 5dp) wokół. Jeśli chcesz usunąć wypełnienie, zobacz Jak usunąć wypełnienie wokół Androida 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 - Testowane. Zgodnie z oczekiwaniami dodaje to dopełnianie do całej kontrolki, a nie między polem wyboru a tekstem.
DougW

Prawdopodobnie lepiej jest mieć tekst w osobnym TextView.
AndrewKS

@AndrewKS - Zły pomysł na użyteczność. Chcę, aby użytkownik mógł dotknąć tekstu i zaznaczyć / odznaczyć pole wyboru. Łamie także wiele funkcji ułatwień dostępu, tak samo jak na stronie internetowej.
DougW

Bad idea for usabilityNie, nie jest. Umieść zarówno pole wyboru, jak i widok tekstu w układzie liniowym i spraw, aby liniowy układ był dotykalny.
Falmarri

1
-1 Ta odpowiedź nie odnosi się do problemu postawionego w pytaniu, który dotyczy luki między obrazem a tekstem
David Laing

2

Jeśli masz niestandardowy selektor obrazu dla pola wyboru lub przycisku radiowego, musisz ustawić tę samą właściwość przycisku i tła, taką jak ta:

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

Możesz kontrolować rozmiar pola wyboru lub wypełnienia przycisku opcji za pomocą właściwości tła.


Nie, nie musisz tego robić. Jest to niedopuszczalne, jeśli masz niestandardowe tło inne niż glif pola wyboru / radiobutton.
andr

2

tylko musisz mieć jeden parametr w pliku xml

android:paddingLeft="20dp"

2

Ustawienie minHeight i minWidth 0dpbyło najczystszym i najprostszym rozwiązaniem dla mnie w systemie 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" />

1

Jeśli tworzysz niestandardowe przyciski, np. Zobacz zmianę wyglądu samouczka pola wyboru

Następnie po prostu zwiększ szerokość btn_check_label_background.9.png, dodając jedną lub dwie kolejne kolumny przezroczystych pikseli na środku obrazu; pozostaw znaczniki z 9 łatami takimi, jakie są.


1

To, co zrobiłem, to posiadanie TextViewi CheckBoxwewnątrz (Relative) Layout. W TextViewwyświetla tekst, który chcę użytkownika, aby zobaczyć, a CheckBoxnie ma żadnego tekstu. W ten sposób mogę ustawić pozycję / wypełnienie w CheckBoxdowolnym miejscu.



0

Musisz dodać rozmiar obrazu, którego używasz, aby dodać dopełnienie do tego rozmiaru. W urządzeniach wewnętrznych z systemem Android są one dostępne do rysowania, które określasz na src, a następnie używają jego rozmiaru. Ponieważ jest to zmienna prywatna i nie ma żadnych pobierających, do których nie można uzyskać dostępu. Ponadto nie możesz uzyskać com.android.internal.R.styleable.CompoundButton i stamtąd można pobrać.

Musisz więc stworzyć swój własny styl (np. Custom_src) lub możesz dodać go bezpośrednio w swojej implementacji 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

Ponieważ prawdopodobnie używasz selektora do rysowania dla swojej android:buttonwłaściwości, musisz dodać android:constantSize="true"i / lub określić domyślną rysowną w następujący sposób:

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

Następnie musisz określić android:paddingLeftatrybut w polu wyboru xml.

Cons:

W edytorze układu pojawi się tekst pod polem wyboru z interfejsem API 16 i niższym, w takim przypadku możesz to naprawić, tworząc niestandardową klasę pola wyboru, jak sugerowano, ale dla interfejsu API poziomu 16.

Racjonalne uzasadnienie:

jest to błąd, ponieważ StateListDrawable#getIntrinsicWidth()wywołanie jest używane wewnętrznie, CompoundButtonale może zwrócić < 0wartość, jeśli nie ma aktualnego stanu i nie jest używany stały rozmiar.


0

Wszystko, co musisz zrobić, aby rozwiązać ten problem, to dodać android:singleLine="true"do checkBoxukładu xml w Androidzie:

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

i nic specjalnego nie zostanie dodane programowo.


0

Obraz pola wyboru zachodził na siebie, gdy używałem własnych drawables z selektora, rozwiązałem to za pomocą poniższego kodu:

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

Dzięki Alex Semeniuk


0

Kończę z tym problemem, zmieniając obrazy. Właśnie dodałem dodatkowe przezroczyste tło w plikach png. To rozwiązanie działa doskonale na wszystkich interfejsach API.


0

Może jest już za późno, ale stworzyłem narzędzia do zarządzania tym problemem.

Po prostu dodaj te metody do swoich narzędzi:

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

I użyj tego:

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

lub tak:

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

-1

Zamiast dostosowywać tekst dla Checkbox, zrobiłem następujące rzeczy i zadziałało to dla wszystkich urządzeń. 1) W XML dodaj pole wyboru i widok tekstu obok siebie; utrzymywanie dystansu. 2) Ustaw rozmiar pola wyboru na 0sp. 3) Dodaj względny tekst do tego widoku obok pola wyboru.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.