Android - Espacement entre CheckBox et texte

256

Existe-t-il un moyen simple d'ajouter un remplissage entre la case à cocher d'un contrôle CheckBox et le texte associé?

Je ne peux pas simplement ajouter des espaces de début, car mon étiquette est multiligne.

En l'état, le texte est beaucoup trop proche de la case à cocher: texte alternatif

DougW
la source
1
Une solution simple serait d'utiliser un TextViewavec drawableLeftet utiliser drawablePaddingpour donner de l'espace au texte. Dans le code, basculez simplement les états sélectionnés et non sélectionnés.
Muhammad Babar
Je viens de remarquer un nouvel attribut xml appelé android: drawablePadding, qui est censé définir l'espacement entre le dessinable et le texte. Je ne l'ai pas essayé, mais je pense que c'est la solution «après coup» de Google pour ce problème.
Peri Hartman

Réponses:

333

Je déteste répondre à ma propre question, mais dans ce cas, je pense que je dois le faire. Après l'avoir vérifié, @Falmarri était sur la bonne voie avec sa réponse. Le problème est que le contrôle CheckBox d'Android utilise déjà la propriété android: paddingLeft pour obtenir le texte où il se trouve.

La ligne rouge montre la valeur de décalage paddingLeft de l'ensemble du CheckBox

texte alternatif

Si je remplace simplement ce remplissage dans ma disposition XML, cela gâche la disposition. Voici ce que fait la définition de paddingLeft = "0":

texte alternatif

Il s'avère que vous ne pouvez pas résoudre ce problème en XML. Vous devez le faire en code. Voici mon extrait de code avec une augmentation de remplissage codée en dur de 10dp.

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

Cela vous donne ce qui suit, où la ligne verte est l'augmentation du rembourrage. C'est plus sûr que de coder en dur une valeur, car différents appareils peuvent utiliser différents drawables pour la case à cocher.

texte alternatif

MISE À JOUR - Comme les gens l'ont récemment mentionné dans les réponses ci-dessous, ce comportement a apparemment changé dans Jelly Bean (4.2). Votre application devra vérifier sur quelle version elle s'exécute et utiliser la méthode appropriée.

Pour 4.3+, il suffit de définir padding_left. Voir la réponse de htafoya pour plus de détails.

DougW
la source
108
Rien de mal à répondre à votre propre question - quelqu'un d'autre aura probablement ce problème à l'avenir et vous venez de donner une bonne réponse complète.
AndrewKS
4
Quel est le problème avec le réglage paddingLeft="48sp"? Fonctionne bien ici, même si je change d'échelle et d'orientation. Votre code m'a donné des valeurs de remplissage erratiques sur une liste d'éléments.
harpo
5
@harpo - Vous n'avez aucune garantie que différents fabricants d'appareils n'utiliseront pas différents graphiques pour la case à cocher, ce qui signifie que votre rembourrage codé en dur peut casser votre présentation visuelle sur différents appareils. Puisque je lis le remplissage actuel et que j'y ajoute, ce ne sera pas un problème, mais vous devez vous assurer de ne le faire qu'une seule fois.
DougW
2
@Blundell - Pas nécessairement. Open source d'Android. Un fournisseur d'appareils pourrait remplacer un graphique totalement différent par une taille totalement différente. Ils aiment faire des trucs comme ça pour une raison quelconque.
DougW
2
Malheureusement, vous ne pouvez pas utiliser cette solution dans getView()un adaptateur personnalisé (si vous recyclez vos vues), car le rembourrage augmentera sans cesse. Pour résoudre ce problème , je devais utiliser quelque chose comme ceci: 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); }. Et puis utiliser PADDINGpour chaque CheckBox que je gonfle:check.setPadding(PADDING, check.getPaddingTop() ...
Alex Semeniuk
133

Étant donné la réponse de @DougW, ce que je fais pour gérer la version est plus simple, j'ajoute à ma vue case à cocher:

android:paddingLeft="@dimen/padding_checkbox"

où le dimen se trouve dans deux dossiers de valeurs:

valeurs

<resources>

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

</resources>

values-v17 (4.2 JellyBean)

<resources>

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

</resources>

J'ai une vérification personnalisée, utilisez le dps à votre meilleur choix.

htafoya
la source
2
C'est la meilleure réponse jusqu'à présent. bien que ce soit vraiment le cas, values-v17car le correctif a été introduit dans l'API 17 (selon certains articles ci-dessus)
icecreamman
Une réponse parfaite, juste pour les apis plus âgés (valeurs / dimens) J'ai mis padding_checkbox à 0dip (sur API 10 la marge est déjà énorme) et pour values-v17 10dip comme suggéré par htafoya.
Yar
70

Utilisez l'attribut android:drawableLeftau lieu de android:button. Afin de définir le remplissage entre l'utilisation du dessin et du texte android:drawablePadding. Pour positionner l'utilisation à tirer 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"
        />

résultat

Trokhymets romains
la source
1
Salut, C'est une bonne méthode, mais notez que vous obtenez une marge supplémentaire gauche bcoz de l'image par défaut de la case à cocher .. toutes les solutions pour cela
Code_Life
4
le set android:background="@android:color/transparent"et la marge gauche disparaîtront
madeuz
2
Le code ci-dessus a parfaitement fonctionné pour mes boutons radio et est cohérent à travers la limite de 4.2 OS. Merci!
gnichola
1
Cela devrait être classé beaucoup plus haut. Comme l'a dit @gnichola, cela fonctionne sur toutes les versions d'Android et est une solution assez propre. Créez un style et affectez-le à votre thème comme ceci: De <item name="android:checkboxStyle">@style/CheckBox</item> cette façon, vous avez défini le style une seule fois et référencé une seule fois.
Rosomack
1
Définissez également l'arrière-plan sur null (ou quelque chose de personnalisé), sinon lollipop + obtient un effet d'ondulation de cercle massif englobant la vue entière. Vous pouvez utiliser un bouton v21 dessinable en utilisant les balises <ripple> pour remettre une ondulation plus appropriée.
Tom
34

Android 4.2 Jelly Bean (API 17) met le texte paddingLeft à partir du buttonDrawable (entre le bord droit). Il fonctionne également pour le mode RTL.

Avant 4.2 paddingLeft ignorait le buttonDrawable - il était pris du bord gauche de la vue CompoundButton.

Vous pouvez le résoudre via XML - définissez paddingLeft sur buttonDrawable.width + requiredSpace sur les androïdes plus anciens. Définissez-le sur requiredSpace uniquement sur l'API 17. Par exemple, utilisez les ressources de dimension et remplacez-les dans le dossier de ressources values-v17.

Le changement a été introduit via android.widget.CompoundButton.getCompoundPaddingLeft ();

kotucz
la source
4
C'est la seule bonne réponse ici - elle identifie le problème et fournit des solutions simples, que j'ai utilisées avec succès dans plusieurs applications commerciales.
madej
1
Comment obtenir buttonDrawable.width en XML ou le coder en dur?
Jared Kells
1
J'ai réussi à résoudre ce problème dans un ancien code en le supprimant android:background="@android:color/transparent".
Sebek
La réponse acceptée est agréable et fonctionne, mais celle-ci est simple et efficace. Cette réponse devrait être acceptée.
Reaz Murshed
27

Oui, vous pouvez ajouter du rembourrage en ajoutant du rembourrage.

android:padding=5dp

Falmarri
la source
4
Cela fonctionne en fait ... en quelque sorte. D'une part, seul paddingLeft est nécessaire, pas tout le padding. Cependant, il semble que le paddingLeft est déjà défini sur une valeur d'environ 40dp. Si je le mets> 40dp, il s'éloigne, si je le mets <40dp, il se déplace sous la case à cocher. Je vais marquer cela comme correct et ouvrir une autre question, car cela me préoccupe.
DougW
Eh bien, je n'ai aucune idée sans voir votre mise en page.
Falmarri
oui ne fonctionne pas .. en particulier appareil samsung j'ai eu un problème.
Ranjith Kumar
1
Ajouter du rembourrage en ajoutant des sons de remplissage légitimes
Sermilion
21

Si vous voulez un design épuré sans codes, utilisez:

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

L'astuce consiste à définir la couleur sur transparent pour android:drawableLeftet à attribuer une valeur à android:drawablePadding. De plus, la transparence vous permet d'utiliser cette technique sur n'importe quelle couleur d'arrière-plan sans effet secondaire, comme une différence de couleur.

ChuongPham
la source
16

API 17 et supérieur, vous pouvez utiliser:

android: paddingStart = "24dp"

API 16 et inférieures, vous pouvez utiliser:

android: paddingLeft = "24dp"

Inmer
la source
1
Très bonne réponse. Je ne peux pas imaginer comment le remplissage donnera l'espace entre la case à cocher et le texte. Habituellement, Padding Left signifie gauche du composant.
Mohamed Ibrahim
14

Dans mon cas, j'ai résolu ce problème en utilisant cet attribut CheckBox suivant dans le XML:

*

android: paddingLeft = "@ dimen / activity_horizontal_margin"

*

Mohammad Zakaria
la source
Très bonne réponse. Je ne peux pas imaginer comment le remplissage donnera l'espace entre la case à cocher et le texte. Habituellement, Padding Left signifie gauche du composant.
Mohamed Ibrahim
13

Solution simple, ajoutez cette ligne dans les propriétés CheckBox , remplacez 10dp par la valeur d'espacement souhaitée

android:paddingLeft="10dp"
Naveed Ahmad
la source
10

Je ne connais pas les gars, mais j'ai testé

<CheckBox android:paddingLeft="8mm" et déplace uniquement le texte vers la droite, pas le contrôle entier.

Ça me va bien.

Tiago
la source
1
Je n'ai pas essayé cela récemment, il est donc possible que cela fonctionne sur un appareil spécifique ou une version plus récente d'Android OS. Je vous recommande fortement de tester sur différentes configurations, car cela n'a certainement pas fonctionné au moment où j'ai posé cette question.
DougW
Je vois cela se comporter différemment entre 2.3.3 et 4.2 (je ne sais pas où entre les deux le changement s'est produit).
Nate
Voulez-vous dire dp pas mm?
Chrispix
10

Pourquoi ne pas simplement étendre l'Android CheckBox pour avoir un meilleur rembourrage à la place. De cette façon, au lieu d'avoir à le corriger dans le code chaque fois que vous utilisez le CheckBox, vous pouvez simplement utiliser le CheckBox fixe à la place.

Première extension de 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));
    }
}

Deuxième dans votre xml au lieu de créer une CheckBox normale, créez votre extension

<com.whatever.CheckBoxWithPaddingFix
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello there" />
w.donahue
la source
2
Vous devez ajouter un «si» pour éviter de le faire si OS> 4.2 parce que dans Jelly Bean, ils ont «corrigé» cela.
Martin Marconcini
1
En fait> = 4,2 (17).
Aleks N.
6

Je viens de conclure à ce sujet:

Remplacez CheckBox et ajoutez cette méthode si vous avez un dessinable personnalisé:

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

}

ou ceci si vous utilisez le système 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;
    }

}

Merci d'avoir répondu :)

PaNaVTEC
la source
4

Ce comportement semble avoir changé dans Jelly Bean. L'astuce paddingLeft ajoute un remplissage supplémentaire, ce qui rend le texte trop à droite. Quelqu'un d'autre l'a remarqué?

extrême
la source
Merci pour la mise à jour! J'ai ajouté une note à ma réponse à ce sujet.
DougW
4

Pour l'espace entre la coche et le texte, utilisez:

android:paddingLeft="10dp"

Mais cela devient plus de 10dp, car la coche contient un remplissage (environ 5dp) autour. Si vous souhaitez supprimer le remplissage, consultez Comment supprimer le remplissage autour d'Android CheckBox :

android:paddingLeft="-5dp"
android:layout_marginStart="-5dp"
android:layout_marginLeft="-5dp"
// or android:translationX="-5dp" instead of layout_marginLeft
CoolMind
la source
2
<CheckBox
        android:paddingRight="12dip" />
AndrewKS
la source
@AndrewKS - Testé. Comme prévu, cela ajoute un remplissage à l'ensemble du contrôle, pas entre la case à cocher et le texte.
DougW
Vous feriez probablement mieux d'avoir le texte dans une TextView distincte.
AndrewKS
@AndrewKS - Mauvaise idée d'utilisation. Je souhaite que l'utilisateur puisse toucher le texte et cocher / décocher la case. Il brise également de nombreuses fonctionnalités d'accessibilité, de la même manière que si vous le faites dans une page Web.
DougW
Bad idea for usabilityNon ce n'est pas. Placez la case à cocher et la vue de texte dans une disposition linéaire et rendez cette disposition linéaire tactile.
Falmarri
1
-1 Cette réponse ne résout pas le problème posé dans la question, qui concerne l'écart entre l'image et le texte
David Laing
2

Si vous avez un sélecteur d'image personnalisé pour la case à cocher ou le bouton radio, vous devez définir le même bouton et la même propriété d'arrière-plan, comme ceci:

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

Vous pouvez contrôler la taille de la case à cocher ou du remplissage des boutons radio avec la propriété background.

Ilya Lisway
la source
Non, vous n'êtes pas obligé de le faire. Ce n'est pas acceptable si vous avez un arrière-plan personnalisé différent du glyphe de case à cocher / radiobutton.
andr
2

seulement vous devez avoir un paramètre dans le fichier xml

android:paddingLeft="20dp"
tej shah
la source
2

Définir minHeight et minWidth 0dpétait la solution la plus propre et la plus directe pour moi sur 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
la source
1

Si vous créez des boutons personnalisés, par exemple, voir changer l'apparence du didacticiel de case à cocher

Augmentez ensuite simplement la largeur de btn_check_label_background.9.png en ajoutant une ou deux colonnes supplémentaires de pixels transparents au centre de l'image; laissez les marqueurs à 9 patchs tels quels.

Keith Beardmore
la source
1

Ce que j'ai fait, c'est d'avoir un TextViewet un à l' CheckBoxintérieur d'un (Relatif) Layout. Le TextViewaffiche le texte que je veux que l'utilisateur voie et le CheckBoxn'a pas de texte. De cette façon, je peux définir la position / le rembourrage de l' CheckBoxendroit où je veux.

mbmc
la source
1

J'ai eu le même problème avec un Galaxy S3 mini (Android 4.1.2) et j'ai simplement étendu ma case à cocher personnalisée pour étendre AppCompatCheckBox au lieu de CheckBox. Maintenant ça marche parfaitement.

Quentin G.
la source
0

Vous devez obtenir la taille de l'image que vous utilisez afin d'ajouter votre rembourrage à cette taille. Sur les internes Android, ils obtiennent le dessin que vous spécifiez sur src et utilisent ensuite sa taille. Puisqu'il s'agit d'une variable privée et qu'il n'y a pas de getters, vous ne pouvez pas y accéder. Vous ne pouvez pas non plus obtenir le com.android.internal.R.styleable.CompoundButton et obtenir le dessinable à partir de là.

Vous devez donc créer votre propre styleable (c'est-à-dire custom_src) ou vous pouvez l'ajouter directement dans votre implémentation du 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
la source
0

Comme vous utilisez probablement un sélecteur de dessin pour votre android:buttonpropriété, vous devez ajouter android:constantSize="true"et / ou spécifier un dessin par défaut comme celui-ci:

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

Après cela, vous devez spécifier l' android:paddingLeftattribut dans votre case à cocher xml.

Les inconvénients:

Dans l'éditeur de mise en page, le texte passe sous la case à cocher avec api 16 et ci-dessous, dans ce cas, vous pouvez le corriger en créant votre classe de case à cocher personnalisée comme suggéré, mais pour le niveau api 16.

Raisonnement:

c'est un bogue car l' StateListDrawable#getIntrinsicWidth()appel est utilisé en interne CompoundButtonmais il peut retourner une < 0valeur s'il n'y a pas d'état actuel et qu'aucune taille constante n'est utilisée.

Gianluca P.
la source
0

Tout ce que vous avez à faire pour surmonter ce problème est d'ajouter android:singleLine="true"à la mise checkBoxen page XML de votre 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"/>

et rien de spécial ne sera ajouté par programme.

Muhammed Refaat
la source
0

L'image de la case à cocher se chevauchait lorsque j'ai utilisé mes propres tirables du sélecteur, j'ai résolu cela en utilisant le code ci-dessous:

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

Merci à Alex Semeniuk

Jaiprakash Soni
la source
0

Je me retrouve avec ce problème en changeant les images. Ajout d'un fond transparent supplémentaire dans les fichiers png. Cette solution fonctionne parfaitement sur toutes les API.

Leo Droidcoder
la source
0

C'est peut-être trop tard, mais j'ai créé des méthodes utilitaires pour gérer ce problème.

Ajoutez simplement ces méthodes à vos utilitaires:

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

Et utilisez comme ceci:

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

ou comme ça:

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

Au lieu d'ajuster le texte de Checkbox, j'ai fait la chose suivante et cela a fonctionné pour moi pour tous les appareils. 1) En XML, ajoutez une case à cocher et une vue de texte adjacentes les unes aux autres; garder une certaine distance. 2) Définissez la taille du texte de la case à cocher sur 0sp. 3) Ajoutez du texte relatif à cette vue de texte à côté de la case à cocher.

Pankaj Deshpande
la source
-3

<CheckBox android:drawablePadding="16dip" - Le rembourrage entre les tirables et le texte.

user1879118
la source