Android: spaziatura tra CheckBox e testo


256

Esiste un modo semplice per aggiungere il riempimento tra la casella di controllo in un controllo CheckBox e il testo associato?

Non posso semplicemente aggiungere spazi iniziali, perché la mia etichetta è multilinea.

Così com'è, il testo è troppo vicino alla casella di controllo: testo alternativo


1
Una soluzione semplice sarebbe usare un TextViewcon drawableLefte usare drawablePaddingper dare spazio al testo. Nel codice basta attivare o disattivare gli stati selezionati.
Muhammad Babar,

Ho appena notato un nuovo attributo xml chiamato android: drawablePadding, che dovrebbe impostare la spaziatura tra il disegno e il testo. Non l'ho provato ma penso che sia la soluzione "post-fact" di Google per questo problema.
Peri Hartman,

Risposte:


333

Odio rispondere alla mia domanda, ma in questo caso penso di doverlo fare. Dopo averlo verificato, @Falmarri era sulla buona strada con la sua risposta. Il problema è che il controllo CheckBox di Android utilizza già la proprietà android: paddingLeft per ottenere il testo dove si trova.

La linea rossa mostra il valore di offset paddingLeft dell'intero CheckBox

testo alternativo

Se ho appena sovrascritto quell'imbottitura nel mio layout XML, il layout è rovinato. Ecco cosa fa l'impostazione paddingLeft = "0":

testo alternativo

Si scopre che non è possibile risolvere questo problema in XML. Lo hai fatto nel codice. Ecco il mio frammento con un aumento dell'imbottitura hardcoded di 10dp.

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

Questo ti dà quanto segue, dove la linea verde è l'aumento dell'imbottitura. Questo è più sicuro dell'hardcoding di un valore, poiché diversi dispositivi potrebbero usare disegnabili diversi per la casella di controllo.

testo alternativo

AGGIORNAMENTO - Come le persone hanno recentemente menzionato nelle risposte di seguito, questo comportamento è apparentemente cambiato in Jelly Bean (4.2). La tua app dovrà verificare su quale versione è in esecuzione e utilizzare il metodo appropriato.

Per 4.3+ sta semplicemente impostando padding_left. Vedi la risposta di htafoya per i dettagli.


108
Nulla di sbagliato nel rispondere alla tua domanda: qualcun altro probabilmente avrà questo problema in futuro e hai appena dato una risposta buona e completa.
AndrewKS,

4
Cosa c'è di sbagliato nell'impostare paddingLeft="48sp"? Funziona bene qui, anche se cambio scala e orientamento. Il tuo codice mi ha fornito valori di riempimento irregolari su un elenco di elementi.
Harpo,

5
@harpo - Non hai alcuna garanzia che produttori diversi di dispositivi non utilizzino grafici diversi per la casella di controllo, il che significa che la tua imbottitura con codice fisso potrebbe interrompere il layout visivo su dispositivi diversi. Dal momento che sto leggendo l'attuale padding e aggiungendo ad esso non sarà un problema, ma devi assicurarti di farlo solo una volta.
DougW

2
@Blundell - Non necessariamente. Open source di Android. Un fornitore di dispositivi potrebbe sostituire un elemento grafico completamente diverso con una dimensione totalmente diversa. Amano fare cose del genere per qualche motivo.
DougW,

2
Sfortunatamente, non è possibile utilizzare questa soluzione getView()nell'adattatore personalizzato (se si riciclano le viste), poiché il riempimento aumenterà all'infinito. Per risolvere questo problema che ho dovuto usare qualcosa di simile a questo: 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); }. E poi uso PADDINGper ogni CheckBox che gonfio:check.setPadding(PADDING, check.getPaddingTop() ...
Alex Semeniuk,

133

Data la risposta di @DougW, ciò che faccio per gestire la versione è più semplice, aggiungo alla mia casella di controllo:

android:paddingLeft="@dimen/padding_checkbox"

dove il dimen si trova in due cartelle di valori:

valori

<resources>

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

</resources>

valori-v17 (4.2 JellyBean)

<resources>

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

</resources>

Ho un controllo personalizzato, usa il dps per la tua scelta migliore.


2
Questa è la risposta migliore finora. sebbene, dovrebbe davvero essere values-v17come la correzione è stata introdotta in API 17 (secondo alcuni post sopra)
icecreamman,

Una risposta perfetta, solo per le vecchie API (valori / dimens) ho impostato padding_checkbox su 0dip (il margine API 10 è già enorme) e per i valori-v17 10dip come suggerito da htafoya.
Yar

70

Usa l'attributo android:drawableLeftinvece di android:button. Per impostare il riempimento tra disegno e testo android:drawablePadding. Per posizionare l'uso del disegno 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"
        />

risultato


1
Ciao, questo è un bel metodo, ma nota che ottieni un margine sinistro extra bcoz dell'immagine predefinita della casella di controllo .. qualsiasi soluzione per questo
Code_Life

4
il android:background="@android:color/transparent"margine impostato e quello sinistro scompariranno
madeuz il

2
Il codice sopra ha funzionato perfettamente per i miei pulsanti di opzione ed è coerente attraverso il limite del sistema operativo 4.2. Grazie!
gnichola,

1
Questo dovrebbe essere classificato molto più in alto. Come diceva @gnichola, funziona su tutte le versioni di Android ed è una soluzione abbastanza pulita. Crea uno stile e assegnalo nel tuo tema in questo modo: in <item name="android:checkboxStyle">@style/CheckBox</item> questo modo, hai lo stile definito una volta e referenziato una sola volta.
Rosomack,

1
Imposta anche lo sfondo su null (o qualcosa di personalizzato), altrimenti lecca-lecca + ottiene un enorme effetto a catena che racchiude l'intera vista. È possibile utilizzare un pulsante v21 estraibile utilizzando i tag <ripple> per reinserire un'ondulazione più appropriata.
Tom

34

Android 4.2 Jelly Bean (API 17) inserisce il riempimento del testo A sinistra dal pulsante Disegnabile (ints bordo destro). Funziona anche per la modalità RTL.

Prima del padding 4.2 La sinistra stava ignorando il buttonDrawable - era preso dal bordo sinistro della vista CompoundButton.

Puoi risolverlo tramite XML - imposta paddingLeft su buttonDrawable.width + richiestoSpace su androidi meno recenti. Impostalo su richiesto Spazio solo su API 17 in su. Ad esempio, utilizzare le risorse dimensione e sovrascrivere nella cartella delle risorse valori-v17.

La modifica è stata introdotta tramite android.widget.CompoundButton.getCompoundPaddingLeft ();


4
È l'unica risposta corretta qui: individua il problema e fornisce soluzioni semplici, che ho usato con successo in più app commerciali.
madej

1
Come si ottiene buttonDrawable.width in XML o lo si codifica?
Jared Kells,

1
Sono riuscito a risolvere questo problema in un vecchio codice rimuovendolo android:background="@android:color/transparent".
Sebek,

La risposta accettata è carina e funzionante, ma questa è semplice ed efficace. Questa dovrebbe essere una risposta accettata.
Reaz Murshed il

27

Sì, puoi aggiungere imbottitura aggiungendo imbottitura.

android:padding=5dp


4
In realtà funziona ... in un certo senso. Per uno, è necessaria solo l'imbottitura Sinistra, non tutta l'imbottitura. Tuttavia, sembra che il paddingLeft sia già impostato su un valore di circa 40dp. Se lo imposto> 40dp si allontana, se lo imposto <40dp si sposta sotto la casella di controllo. Lo segnerò come corretto e aprirò un'altra domanda, perché ho delle preoccupazioni al riguardo.
DougW,

Beh, non ne ho idea senza vedere il tuo layout.
Falmarri,

si non funziona..particolarmente il dispositivo Samsung ho avuto problemi.
Ranjith Kumar,

1
Aggiungere padding aggiungendo suoni di padding legittimi!
Sermilion

21

Se si desidera un design pulito senza codici, utilizzare:

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

Il trucco è impostare il colore su trasparente per android:drawableLefte assegnare un valore per android:drawablePadding. Inoltre, la trasparenza consente di utilizzare questa tecnica su qualsiasi colore di sfondo senza l'effetto collaterale, come la mancata corrispondenza del colore.


16

API 17 e successive, puoi usare:

Android: paddingStart = "24dp"

API 16 e precedenti, è possibile utilizzare:

Android: paddingLeft = "24dp"


1
Ottima risposta Non riesco a immaginare come l'imbottitura darà lo spazio tra la casella di controllo e il testo. Di solito imbottitura sinistra significa sinistra del componente.
Mohamed Ibrahim il

14

Nel mio caso ho risolto questo problema utilizzando questo seguente attributo CheckBox nell'XML:

*

Android: paddingLeft = "@ dimen / activity_horizontal_margin"

*


Ottima risposta Non riesco a immaginare come l'imbottitura darà lo spazio tra la casella di controllo e il testo. Di solito imbottitura sinistra significa sinistra del componente.
Mohamed Ibrahim il

13

Soluzione semplice, aggiungi questa riga nelle proprietà CheckBox , sostituisci 10dp con il valore di spaziatura desiderato

android:paddingLeft="10dp"

10

Non conosco ragazzi, ma ho provato

<CheckBox android:paddingLeft="8mm" e sposta solo il testo a destra, non l'intero controllo.

Mi va bene.


1
Non ci ho provato di recente, quindi è certamente possibile che funzioni su un dispositivo specifico o su una versione del sistema operativo Android più recente. Consiglio vivamente di testare su diverse configurazioni, perché sicuramente non ha funzionato al momento in cui ho posto questa domanda.
DougW,

Sto vedendo che ciò si comporta in modo diverso tra 2.3.3 e 4.2 (non sono sicuro di dove si sia verificato il cambiamento).
Nate,

Intendi dp non mm?
Chrispix,

10

Perché non solo estendere Android CheckBox per avere un'imbottitura migliore invece. In questo modo invece di doverlo correggere nel codice ogni volta che usi CheckBox, puoi semplicemente usare CheckBox fisso.

Prima estendi 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));
    }
}

Secondo nel tuo XML invece di creare un normale CheckBox crea quello esteso

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

2
Dovresti aggiungere un 'if' per evitare di farlo se OS> 4.2 perché in Jelly Bean hanno "risolto" questo.
Martin Marconcini,

1
In realtà> = 4,2 (17).
Aleks N.

6

Ho appena concluso su questo:

Sostituisci CheckBox e aggiungi questo metodo se hai un disegno personalizzato:

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

}

o questo se si utilizza il sistema di disegno:

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

}

Grazie per la risposta :)


4

Questo comportamento sembra essere cambiato in Jelly Bean. Il trucco paddingLeft aggiunge ulteriore padding, facendo apparire il testo troppo a destra. Qualcun altro lo nota?


Grazie per l'aggiornamento! Ho aggiunto una nota alla mia risposta a riguardo.
DougW,

4

Per lo spazio tra il segno di spunta e il testo utilizzare:

android:paddingLeft="10dp"

Ma diventa più di 10dp, perché il segno di spunta contiene un'imbottitura (circa 5dp) intorno. Se desideri rimuovere l'imbottitura, vedi Come rimuovere l'imbottitura attorno ad 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 - Testato. Come previsto, questo aggiunge il riempimento all'intero controllo, non tra la casella di controllo e il testo.
DougW,

Probabilmente stai meglio avere il testo in un TextView separato.
AndrewKS,

@AndrewKS - Cattiva idea per l'usabilità. Voglio che l'utente sia in grado di toccare il testo e selezionare / deselezionare la casella di controllo. Inoltre, interrompe molte funzioni di accessibilità, allo stesso modo in cui lo si fa in una pagina Web.
DougW,

Bad idea for usabilityNo non lo è. Metti sia la casella di controllo che la visualizzazione di testo in un layout lineare e rendi tangibile quell'aspetto lineare.
Falmarri,

1
-1 Questa risposta non affronta il problema posto nella domanda, che riguarda il divario tra l'immagine e il testo
David Laing

2

Se si dispone di un selettore di immagini personalizzato per la casella di controllo o il pulsante di opzione, è necessario impostare lo stesso pulsante e la stessa proprietà di sfondo come questa:

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

Puoi controllare le dimensioni della casella di controllo o del pulsante di opzione con la proprietà di sfondo.


No, non devi farlo. Ciò non è accettabile se si dispone di uno sfondo personalizzato diverso dal glifo della casella di controllo / pulsante di opzione.
andr

2

solo tu devi avere un parametro nel file xml

android:paddingLeft="20dp"

2

L'impostazione di minHeight e minWidth su 0dpera la soluzione più pulita e diretta per me su 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

Quello che ho fatto è avere a TextViewe a CheckBoxdentro a (Relativo) Layout. I TextViewvisualizza il testo che voglio all'utente di vedere, e il CheckBoxnon avere alcun testo. In questo modo, posso impostare la posizione / imbottitura di CheckBoxdove voglio.


1

Ho avuto lo stesso problema con un Galaxy S3 mini (Android 4.1.2) e ho semplicemente reso la mia casella di controllo personalizzata estesa AppCompatCheckBox invece di CheckBox. Ora funziona perfettamente.


0

È necessario ottenere le dimensioni dell'immagine che si sta utilizzando per aggiungere l'imbottitura a queste dimensioni. Negli interni Android, ottengono il disegno che specifichi su src e ne usano le dimensioni in seguito. Dal momento che è una variabile privata e non ci sono getter non è possibile accedervi. Inoltre non puoi ottenere il com.android.internal.R.styleable.CompoundButton e ottenere il disegno da lì.

Quindi devi creare il tuo stile (cioè custom_src) o puoi aggiungerlo direttamente nella tua implementazione di 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

Dato che probabilmente usi un selettore di disegni per la tua android:buttonproprietà, devi aggiungere android:constantSize="true"e / o specificare un disegno di default come questo:

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

Successivamente è necessario specificare l' android:paddingLeftattributo nella casella di controllo xml.

Contro:

Nell'editor di layout troverai il testo che passa sotto la casella di controllo con api 16 e precedenti, in tal caso puoi risolverlo creando la tua classe di casella di controllo personalizzata come suggerita ma per api livello 16.

Fondamento logico:

è un bug in quanto la StateListDrawable#getIntrinsicWidth()chiamata viene utilizzata internamente CompoundButtonma può restituire < 0valore se non c'è stato corrente e non viene utilizzata una dimensione costante.


0

Tutto quello che devi fare per superare questo problema è aggiungere android:singleLine="true"al checkBoxtuo layout xml Android:

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

e nulla di speciale verrà aggiunto a livello di codice.


0

L'immagine della casella di controllo si sovrapponeva quando ho usato i miei drawable dal selettore, ho risolto questo problema usando il codice seguente:

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

Grazie ad Alex Semeniuk


0

Concludo con questo problema cambiando le immagini. Ho appena aggiunto uno sfondo extra trasparente nei file png. Questa soluzione funziona in modo eccellente su tutte le API.


0

Forse è troppo tardi, ma ho creato metodi di utilità per gestire questo problema.

Aggiungi questi metodi ai tuoi programmi di utilità:

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

E usa così:

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

o in questo modo:

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

-1

Invece di modificare il testo per Checkbox, ho fatto la seguente cosa e ha funzionato per me per tutti i dispositivi. 1) In XML, aggiungi la casella di controllo e una visualizzazione di testo adiacente l'uno dopo l'altro; mantenendo una certa distanza. 2) Impostare la dimensione del testo della casella di controllo su 0sp. 3) Aggiungi testo relativo a quella vista di testo accanto alla casella di controllo.


-3

<CheckBox android:drawablePadding="16dip" - L'imbottitura tra i disegni e il testo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.