安卓自定义复选框图片

194

有没有一种简单的方法可以为复选框使用自定义图像?我正在寻找复制Gmail的“加星”行为。因此,我想要一个复选框,在选中时是填充的星星。当未选中时是空星星。我必须使用imageview并自己编写逻辑吗?

12个回答

316

创建一个可绘制的复选框选择器:

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

请确保您的复选框代码如下 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" />

你在哪个记录中指定了这个选择器?是在你指定 CheckBox 的 XML 文件本身中吗? - Tom Hammond
Tom:在drawable文件夹中创建您的选择器,在layout文件夹中创建复选框。 - Mohamed Hisham Ibn Hanifa
1
我不得不将 CheckBox 中的“button”更改为“background”。 - Francisco Corrales Morales
有关填充,请参见https://dev59.com/mm855IYBdhLWcg3w_5qm - PiTheNumber
2
我将我的项目升级到了Android X,但在此之后,我无法像您之前说的那样自定义复选框,因为在API级别21之前,android:button不起作用。 - Misagh Aghakhani
显示剩余4条评论

129

复选框作为按钮的子元素,您可以按照此处描述的“按钮样式”(链接),给您的复选框设置带有多个状态的背景图像:

... 并在此处(链接)进行示例说明:


27
谢谢,我实际上在这里找到了我需要的东西http://it-ride.blogspot.com/2010/04/how-to-android-favorite-button-right.html,但是如果我想要一个真正自定义的图片,我必须按照你的方法去做= P。 - Falmarri
2
谢谢。这正是我一直在寻找的 - 我已经弄清楚了整个状态的问题,但我一直在设置android:background而不是android:button,结果出现了2个按钮。现在一切都很好运行。 - Artem Russakovskii
1
下面的 android:button 解决方案比使用背景属性要好得多! - Orabîg
8
@Orabîg: 这个踩票是错误的。问题已经得到完美回答(“自定义复选框图像”)。这个特定星形按钮存在快捷方式的事实并不使这个答案无效。 - ereOn
虽然这可能是一篇旧帖子,但我想补充一下,Android Studio也使用android:button="@android:drawable/btn_star"方法。 - Angry 84
显示剩余3条评论

45

将 android-sdk/platforms/android-#/data/res/drawable 中的 btn_check.xml 文件复制到您的项目drawable文件夹中,并将“on”和“off”图像状态更改为您自定义的图像。

然后您的xml只需要添加 android:button="@drawable/btn_check"

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

如果您想使用不同的默认Android图标,可以使用android:button="@android:drawable/..."


2
不良建议。图标可能会从一个版本更改到另一个版本,并且有可能在某些版本中完全消失。如果你真的喜欢默认图标,可以从源代码中获取它。 - Korniltsev Anatoly
你是在说直接通过 "@android:drawable/..." 引用默认图标是个不好的想法,还是整个过程都不好? - WOUNDEDStevenJones
2
引用 Holo 图标将会在 Honeycomb 之前的设备上导致应用程序崩溃。维护和调试此类问题非常困难。因此,我通常不仅复制 XML,还复制图像,以确保资源能够被找到。此外,这也非常重要,以确保 UI 在每个设备上看起来都一样。 - Korniltsev Anatoly

27

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

1
一些解释会帮助新用户理解您的代码是如何解决这个问题的。 - Brian Tompsett - 汤莱恩

6
如果您有Android开源代码,可以在以下目录中找到样式定义:
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>

5

根据 Enselic 和 Rahul 的答案。

对我来说可行(在 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" />

3

试一下 -

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

添加此属性 -
<declare-styleable name="CheckBoxImageView">
        <attr name="default_img" format="integer"/>
        <attr name="checked_img" format="integer"/>
        <attr name="checked" format="boolean"/>
</declare-styleable>

使用方法 -

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

它将解决您所有的问题。


缺少 onSaveInstanceState()onRestoreInstanceState() 方法,我认为在旋转时选中的状态会丢失。 - EpicPandaForce

2
另一个选择是使用带有空背景和自定义按钮的ToggleButton
下面是一个示例,其中包括对文本颜色的选择器。
<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>

2
如果您正在使用自定义适配器,则必须使用android:focusable="false"android:focusableInTouchMode="false",以使在使用复选框时列表项可点击。
<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"/>

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>

2
如果您使用 androidx.appcompat:appcompat 并希望自定义可绘制对象(类型为 selector,具有 android:state_checked),以便在旧平台版本上和新平台版本上都能正常工作,则需要使用:
    <CheckBox
        app:buttonCompat="@drawable/..."

替代

    <CheckBox
        android:button="@drawable/..."

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接