Image de case à cocher personnalisée Android

185

Existe-t-il un moyen simple d'utiliser une image personnalisée pour une case à cocher? Je cherche à dupliquer le comportement "étoilé" de gmail. Je veux donc avoir une case à cocher qui, lorsqu'elle est cochée, est une étoile remplie. Et quand elle n'est pas cochée, c'est une étoile vide. Dois-je utiliser une imageview et faire ma propre logique moi-même?

Falmarri
la source

Réponses:

129

Les cases à cocher étant des enfants de Button, vous pouvez simplement donner à votre case à cocher une image d'arrière-plan avec plusieurs états comme décrit ici , sous "Style de bouton":

... et illustré ici :

Jean
la source
26
Merci, j'ai trouvé exactement ce dont j'avais besoin ici it-ride.blogspot.com/2010/04/ ... mais j'aurais dû le faire à votre façon si je voulais une vraie image personnalisée = P
Falmarri
2
Merci. Exactement ce que je cherchais - j'ai compris tout l'état, mais j'ai configuré android: background au lieu d'Android: button et j'ai fini avec 2 boutons à la place. Maintenant, tout fonctionne bien.
Artem Russakovskii
1
-1. La android:buttonsolution ci-dessous est bien meilleure que l'utilisation de l'attribut d'arrière-plan!
Orabîg
8
@ Orabîg: Ce vote défavorable est faux. La question est parfaitement répondue ("Image de la case à cocher personnalisée"). Le fait qu'un raccourci existe pour ce bouton étoilé particulier n'invalide pas cette réponse.
ereOn
Bien que ce soit peut-être un ancien message, j'aimerais ajouter que le studio Android utilise également la méthode android: button = "@ android: drawable / btn_star"
Angry 84
297

Créez un sélecteur de case à cocher dessinable:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/checkbox" 
          android:state_checked="false"/>
    <item android:drawable="@drawable/checkboxselected" 
          android:state_checked="true"/>
    <item android:drawable="@drawable/checkbox"/>    
</selector>

Assurez-vous que votre case à cocher est comme ceci android:button="@drawable/checkbox_selector"

<CheckBox
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:button="@drawable/checkbox_selector"
    android:text="CheckBox"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:textColor="@color/Black" />
Mohamed Hisham Ibn Hanifa
la source
Dans quel enregistrement spécifiez-vous ce sélecteur? Dans le fichier XML lui-même, où vous spécifiez également la CheckBox?
Tom Hammond
Tom: créez votre sélecteur dans le dossier dessinable et la case à cocher dans le dossier layout
Mohamed Hisham Ibn Hanifa
J'ai dû changer «bouton» pour «arrière-plan» dans la CheckBox
Francisco Corrales Morales
Pour le remplissage, voir stackoverflow.com/questions/4037795/…
PiTheNumber
2
J'ai mis à niveau mon projet vers Android X après cela, je ne pouvais pas personnaliser ma case à cocher comme vous l'avez dit avant le niveau 21 de l'API et Android: le bouton ne fonctionne pas.
Misagh Aghakhani
45

Copiez le btn_check.xml de android-sdk / plates-formes / android - # / data / res / drawable dans le dossier dessinable de votre projet et modifiez les états d'image «on» et «off» en vos images personnalisées.

Ensuite, votre xml aura juste besoin android:button="@drawable/btn_check"

<CheckBox
    android:button="@drawable/btn_check"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:checked="true" />

Si vous souhaitez utiliser différentes icônes Android par défaut, vous pouvez utiliser android:button="@android:drawable/..."

BlesséStevenJones
la source
2
Mauvais conseil. Les icônes peuvent être modifiées d'une version à l'autre et peuvent disparaître du tout. Si vous aimez vraiment l'icône par défaut, vous pouvez la récupérer à partir des sources.
Korniltsev Anatoly
Êtes-vous en train de dire que référencer les icônes par défaut directement via "@android: drawable / ..." est une mauvaise idée, ou ce processus entièrement?
BlesséStevenJones
2
Exemple: la référence aux icônes holo plantera votre application sur les appareils pré-nid d'abeille. Il est vraiment difficile de gérer et de déboguer de tels problèmes. Donc, je copie généralement non seulement xml, mais aussi les images pour être sûr que les ressources seront trouvées. Ceci est également très important pour que l'interface utilisateur soit identique sur tous les appareils.
Korniltsev Anatoly
15

res / drawable / day_selector.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android" >
        <item android:drawable="@drawable/dayselectionunselected"
              android:state_checked="false"/>
        <item android:drawable="@drawable/daysselectionselected"
              android:state_checked="true"/>
        <item android:drawable="@drawable/dayselectionunselected"/>
    </selector>

res / layout / my_layout.xml

<CheckBox
    android:id="@+id/check"
    android:layout_width="39dp"
    android:layout_height="39dp"
    android:background="@drawable/day_selector"
    android:button="@null"
    android:gravity="center"
    android:text="S"
    android:textColor="@color/black"
    android:textSize="12sp" />
Rahul
la source
1
Certaines explications aideraient les nouveaux utilisateurs à comprendre comment votre code résout le problème.
Brian Tompsett - 汤 莱恩
7

Si vous avez du code open source Android, vous pouvez trouver la définition des styles sous:
src / frameworks / base / core / res / res / values

<style name="Widget.CompoundButton.CheckBox">
    <item name="android:background">
        @android:drawable/btn_check_label_background
    </item>
    <item name="android:button">
        ?android:attr/listChoiceIndicatorMultiple
    </item>
</style>
achellies
la source
4

Essayez-le -

package com;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;



public class CheckBoxImageView extends ImageView implements View.OnClickListener {
    boolean checked;
    int defImageRes;
    int checkedImageRes;
    OnCheckedChangeListener onCheckedChangeListener;

    public CheckBoxImageView(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        init(attr, defStyle);
    }

    public CheckBoxImageView(Context context, AttributeSet attr) {
        super(context, attr);
        init(attr, -1);
    }

    public CheckBoxImageView(Context context) {
        super(context);
    }

    public boolean isChecked() {
        return checked;
    }

    public void setChecked(boolean checked) {
        this.checked = checked;
        setImageResource(checked ? checkedImageRes : defImageRes);
    }

    private void init(AttributeSet attributeSet, int defStyle) {
        TypedArray a = null;
        if (defStyle != -1)
            a = getContext().obtainStyledAttributes(attributeSet, R.styleable.CheckBoxImageView, defStyle, 0);
        else
            a = getContext().obtainStyledAttributes(attributeSet, R.styleable.CheckBoxImageView);
        defImageRes = a.getResourceId(0, 0);
        checkedImageRes = a.getResourceId(1, 0);
        checked = a.getBoolean(2, false);
        a.recycle();
        setImageResource(checked ? checkedImageRes : defImageRes);
        setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        checked = !checked;
        setImageResource(checked ? checkedImageRes : defImageRes);
        onCheckedChangeListener.onCheckedChanged(this, checked);
    }

    public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
        this.onCheckedChangeListener = onCheckedChangeListener;
    }

    public static interface OnCheckedChangeListener {
        void onCheckedChanged(View buttonView, boolean isChecked);
    }
}

Ajouter cet attrib -

<declare-styleable name="CheckBoxImageView">
        <attr name="default_img" format="integer"/>
        <attr name="checked_img" format="integer"/>
        <attr name="checked" format="boolean"/>
</declare-styleable>

Utiliser comme -

 <com.adonta.ziva.consumer.wrapper.CheckBoxImageView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/checkBox"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:clickable="true"
        android:padding="5dp"
        app:checked_img="@drawable/check_box_checked"
        app:default_img="@drawable/check_box" />

Il corrigera tous vos problèmes.

Néo
la source
Il manque les méthodes onSaveInstanceState()et onRestoreInstanceState(), je pense que l'état vérifié serait perdu lors de la rotation
EpicPandaForce
2

Une autre option consiste à utiliser un ToggleButton avec un arrière-plan nul et un bouton personnalisé.

Ci-dessous un exemple qui inclut également un sélecteur de couleur de texte.

<ToggleButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:button="@drawable/toggle_selector"
    android:background="@null"
    android:paddingLeft="10dp"
    android:layout_centerHorizontal="true"
    android:gravity="center"
    android:textColor="@drawable/toggle_text"
    android:textOn="My on state"
    android:textOff="My off state" />

toggle_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_checked="true"
        android:drawable="@drawable/state_on" />

    <item
        android:drawable="@drawable/state_off" />

</selector>

toggle_text.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:state_checked="true"
        android:color="@color/app_color" />

    <item
        android:color="@android:color/darker_gray" />

</selector>
androidevil
la source
2

Si vous utilisez des adaptateurs personnalisés, android:focusable="false"et que android:focusableInTouchMode="false"vous souhaitez que les éléments de liste soient cliquables lors de l'utilisation de la case à cocher.

<CheckBox
        android:id="@+id/checkbox_fav"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:button="@drawable/checkbox_layout"/>

Dans drawable> checkbox_layout.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/uncked_checkbox"
        android:state_checked="false"/>
    <item android:drawable="@drawable/selected_checkbox"
        android:state_checked="true"/>
    <item android:drawable="@drawable/uncked_checkbox"/>
</selector>
Chitransh Goud
la source
2

Si vous utilisez androidx.appcompat: appcompat et que vous souhaitez qu'un dessin personnalisé (de type selectorwith android:state_checked) fonctionne sur les anciennes versions de plate-forme en plus des nouvelles versions de plate-forme, vous devez utiliser

    <CheckBox
        app:buttonCompat="@drawable/..."

au lieu de

    <CheckBox
        android:button="@drawable/..."
Enselic
la source
2

Basé sur les réponses d'Enselic et Rahul.

Cela fonctionne pour moi (avant et après l'API 21):

<CheckBox
    android:id="@+id/checkbox"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:text=""
    android:gravity="center"

    android:background="@drawable/checkbox_selector"
    android:button="@null"
    app:buttonCompat="@null" />
Alexrnov
la source