文档章节

Android 修正 CheckBox 疑似bug

 落叶逐风
发布于 2016/07/15 20:25
字数 971
阅读 52
收藏 0

        如题,我们在实际开发中有时候需要手动设置CheckBox 的 isChecked 属性,但是却又不想触发OnCheckedChangeListener的回调事件,比如这个需求:

用户需要在一堆选项中选出若干个选项,但是选择的项数有不能超过某个最大值,那么问题来了,当用户选择的数量达到 (临界值+1)的时候,当前的这个CheckBox是会处于选中状态的,这就需要用代码去掉这个选择,再提示用户不能再选了,那么如何去掉呢?最简单的方法就是调用CheckBox的setChecked(boolean isChecked) 方法,(我不知道是否还真有其他更简洁的办法),但是这个方法又触发了OnCheckedChangeListener 的onCheckedChanged 方法……,然后你就会发现你明明写的代码没有问题,但怎么执行都到不到正确的结果,再检查多遍依然如此,这时候你就想砸电脑了……

        那么如何让它去掉选择状态而不触发回调事件呢?我们从源码入手来分析这个问题。跟踪CheckBox的setChecked(boolean checked) 发现这是它父类 CompoundButton 的方法,源码如下:

 /**
     * <p>Changes the checked state of this button.</p>
     *
     * @param checked true to check the button, false to uncheck it
     */
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;
            refreshDrawableState();
            notifyViewAccessibilityStateChangedIfNeeded(
                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);

            // Avoid infinite recursions if setChecked() is called from a listener
            if (mBroadcasting) {
                return;
            }

            mBroadcasting = true;
            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
            }
            if (mOnCheckedChangeWidgetListener != null) {
                mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
            }

            mBroadcasting = false;            
        }
    }

        这个方法中可以看到,它先去检查你传入的这个checked值是否和之前的值一样,若是一样的话就不再执行了(就是说本来就是选中状态(或未选中状态),你又去给它设置了同样的状态),如果不同(你意图改变CheckBox的状态),则将你设置的这个值(状态)作为新的值(状态),并且更新UI显示,再然后去检查这个CheckBox是否有OnCheckedChangeListener,若有,则会调用监听器的的回调方法。

        到这里思路就很明确了,我们的目的就是要让它改变状态但不触发回调事件,如果能源码编译就很爽了,直接改源码里的这个方法,增加一个boolean 类型的参数,这个参数决定是否触发回调事件,然而大多数人到这里只是想想就放弃了,没必要为了这么点问题去搞个源码编译。既然搞不了,那我们就另寻出路,相信条条大路通罗马,最简单粗暴的做法是自定义一个CheckBox,然后新增一个setChecked(boolean checked , boolean isNotifyListener) 方法去解决这个问题。为了不说废话,以下给出全部代码:


import android.content.Context;
import android.util.AttributeSet;
import android.widget.CheckBox;

/**
 * Created by ning on 2016/7/15.
 * Summary : 这个类提供setChecked(boolean checked , boolean isNotifyListener) 方法,当第二个参数为false时
 * CheckBox只会更新状态,不会触发CheckedChangeListener的回调方法
 * 
 */
public class FiexbleCheckBox extends CheckBox {
    private OnCheckedChangeListener mOnCheckedChangeListener;

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

    public FiexbleCheckBox(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FiexbleCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public FiexbleCheckBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public CharSequence getAccessibilityClassName() {
        return CheckBox.class.getName();
    }
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeListener = listener;
        super.setOnCheckedChangeListener(listener);
    }

    public void setChecked(boolean checked , boolean isNotifyListener) {

        if(isNotifyListener){
            super.setChecked(checked);
        }else{
            if(mOnCheckedChangeListener!=null){
                super.setOnCheckedChangeListener(null);
                super.setChecked(checked);
                setOnCheckedChangeListener(mOnCheckedChangeListener);
            }else{
                super.setChecked(checked);
            }

        }
    }
}

现在你想只更新CheckBox状态又不想触发回调事件,第二个参数传false就ok了 ,好了,至此,我们已经完美的解决了这个问题(其实还可以再扯点儿的,但是都下班好一会儿了,只想着赶紧写完走人……)。

文章原地址:http://my.oschina.net/u/2500514/blog/712782

© 著作权归作者所有

粉丝 1
博文 4
码字总数 1878
作品 0
朝阳
私信 提问
Genius-Android 2.3.0 发布,Android 开源框架

Genius-Android是什么? Genius-Android 是 Android 中一些常用的的方法集合, Genius 提供6个基本板块: app (Ui) animation (动画) widget (Material控件) command (命令行) net tool...

Qiujuer
2015/02/11
5.2K
11
Genius-Android 2.4.0 发布,Android 开源框架

Genius-Android是什么? Genius-Android 是 Android 中一些常用的的方法集合, Genius 提供6个基本板块: app (Ui) animation (动画) widget (Material控件) command (命令行) net tool...

Qiujuer
2015/03/03
8.9K
10
fastjson 1.1.49 发布,进一步提升性能

fastjson 1.1.49 发布了,进一步提升性能,提升json_string -> JSONObject之间的转换性能。在android 5下比原生org.json性能快30%,在android 6下接近原生org.json的性能。back port 1.2.x版...

oschina
2016/04/18
2.6K
7
怎么解决ListView,EditText,CheckBox三个共存的焦点问题??

当我不加任何 android:focusable="true" 的时候, CheckBox,和EditText能获取到焦点,而EditText获取不到焦点。。 而当我 EditText的焦点加上: android:focusable="true" 的时候, CheckB......

mimixi666
2014/01/15
2.3K
0
fastjson 1.1.55 android 发布,Bug 修复

fastjson 1.1.55.android 发布了, 这是一个针对 android 发布的小版本,例行的 BUG 修复功能增强,是针对上一个android 版本 1.1.54.android 的升级。 fastjson 的 android 版本针对 androi...

wenshao
2016/11/20
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
今天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
今天
4
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
今天
6
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
今天
7
0
Python机器学习之数据探索可视化库yellowbrick

背景介绍 从学sklearn时,除了算法的坎要过,还得学习matplotlib可视化,对我的实践应用而言,可视化更重要一些,然而matplotlib的易用性和美观性确实不敢恭维。陆续使用过plotly、seaborn,...

yeayee
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部