Imagem da caixa de seleção personalizada android

182

Existe uma maneira fácil de usar uma imagem personalizada para uma caixa de seleção? Estou procurando duplicar o comportamento "estrelado" do gmail. Então, eu quero ter uma caixa de seleção que, quando marcada, é uma estrela preenchida. E quando desmarcada é uma estrela vazia. Preciso usar uma visualização de imagem e fazer minha própria lógica?

Falmarri
fonte

Respostas:

128

Como as caixas de seleção são filhos do Button, é possível fornecer uma imagem de plano de fundo à sua caixa de seleção com vários estados, conforme descrito aqui , em "Estilo do botão":

... e exemplificado aqui :

Jean
fonte
26
Obrigado, eu realmente encontrei exatamente o que eu precisava aqui it-ride.blogspot.com/2010/04/... mas eu teria que fazer do seu jeito, se eu queria uma verdadeira imagem personalizada = P
Falmarri
2
Obrigado. Exatamente o que eu estava procurando - eu descobri o estado inteiro, mas estou definindo o botão android: background em vez do android: e acabei com dois botões. Agora tudo funciona bem.
Artem Russakovskii
1
-1. A android:buttonsolução abaixo é muito melhor do que usar o atributo background!
Orabîg 18/09/12
8
@ Orabîg: Este voto negativo está errado. A pergunta é perfeitamente respondida ("Imagem da caixa de seleção personalizada"). O fato de existir um atalho para esse botão com estrela em particular não invalida esta resposta.
17/10/2012
Enquanto este talvez um post antigo, gostaria de acrescentar que estúdio Android também usa o android: botão = "@ android: / drawable btn_star" método
irritado 84
289

Crie um seletor de caixa de seleção extraível:

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

Verifique se a sua caixa de seleção é assim 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
fonte
Em que registro você especifica esse seletor? Dentro do próprio arquivo XML, onde você também está especificando a caixa de seleção?
Tom Hammond
Tom: crie seu seletor na pasta drawable e marque a caixa no layout layout
Mohamed Hisham Ibn Hanifa
Eu tive que mudar 'botão
Francisco Corrales Morales
Para preenchimento, consulte stackoverflow.com/questions/4037795/…
PiTheNumber
2
Atualizei meu projeto para o android x depois disso, não consegui personalizar minha caixa de seleção, como você disse antes da API 21 e do android: botão não funciona.
Misagh Aghakhani
44

Copie o btn_check.xml de android-sdk / platform / android - # / data / res / drawable para a pasta drawable do seu projeto e altere os estados da imagem 'on' e 'off' para as imagens personalizadas.

Então seu xml precisará apenas android:button="@drawable/btn_check"

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

Se você quiser usar diferentes ícones padrão do Android, poderá usar android:button="@android:drawable/..."

WOUNDEDStevenJones
fonte
2
Mau conselho. Os ícones podem ser alterados de versão para versão e podem desaparecer. Se você realmente gosta do ícone padrão, pode obtê-lo de fontes.
Korniltsev Anatoly 13/10/12
Você está dizendo que referenciar os ícones padrão diretamente via "@android: drawable / ..." é uma má idéia ou esse processo é inteiramente?
WOUNDEDStevenJones
2
Exemplo: a referência aos ícones holo trava seu aplicativo em dispositivos pré-alveolares. É realmente difícil manter e depurar esses problemas. Por isso, geralmente copio não apenas o xml, mas as imagens também têm uma porcentagem de certeza de que os recursos serão encontrados. Isso também é muito importante para garantir que a interface do usuário tenha a mesma aparência em todos os dispositivos.
Korniltsev Anatoly 18/10/12
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
fonte
1
Alguma explicação ajudaria os novos usuários a entender como o seu código resolve o problema.
Brian Tompsett -
7

Se você possui código-fonte aberto Android, pode encontrar a definição de estilos em:
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
fonte
4

Tente -

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

Adicione este atributo -

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

Use like -

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

Ele irá corrigir todos os seus emblemas.

Neo
fonte
Está faltando o onSaveInstanceState()e onRestoreInstanceState()métodos, eu acho que o estado verificado seria perdido na rotação
EpicPandaForce
2

Outra opção é usar um ToggleButton com plano de fundo nulo e um botão personalizado.

Abaixo um exemplo que também inclui um seletor para a cor do texto.

<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
fonte
2

Se você estiver usando adaptadores personalizados android:focusable="false"e android:focusableInTouchMode="false"não tiver interesse em tornar os itens da lista clicáveis ​​ao usar a caixa de seleção.

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

Em 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
fonte
1

Se você usa androidx.appcompat: appcompat e deseja que um drawable personalizado (do tipo selectorwith android:state_checked) funcione nas versões antigas da plataforma, além das novas, é necessário usar

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

ao invés de

    <CheckBox
        android:button="@drawable/..."
Enselic
fonte
1

Baseado nas respostas Enselic e Rahul.

Funciona para mim (antes e depois da 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
fonte