一些View的checked状态,与onClickListener, onCheckedChangeListener,顺序与时机

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

前言

使用RadioButton和Checkbox,Switch这类依赖checked标签来进行工作的view来说,经常会遇到一些checked状态混乱,与click事件混淆,onClickListener与onCheckedChangeListener混淆不清的情况,在这里做如下总结。

checked状态刷新时机

从framework源码来看。

首先,此类view均继承自CompoundButton,也就是说他们的checked逻辑基本都是一样的。

查找CompoundButton里面对mChecked这一变量的修改发现,在toggle方法内调用:

@Override
    public void toggle() {
        setChecked(!mChecked);
    }

继续检查到toggle方法,是在performClick中调用的,可以看到,在调用super的performClick之前,首先调用了toggle:

@Override
    public boolean performClick() {
        toggle();

        final boolean handled = super.performClick();
        if (!handled) {
            // View only makes a sound effect if the onClickListener was
            // called, so we'll need to make one here instead.
            playSoundEffect(SoundEffectConstants.CLICK);
        }

        return handled;
    }

接下来看一下setChecked方法:

@Override
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mCheckedFromResource = false;
            mChecked = checked;
            refreshDrawableState();

            ...

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

            ...

也就是说,在view运行到自己的performClick时,会先刷新view的checked状态,并且回调onCheckedChangeListener,这就比较清晰了,因为onClickListener是需要在super.performClick中才会被调用的。

常见问题

在点击事件中,使用checked状态

经过上面分析,在onClick被调用前,checked状态已经刷新了并且onCheckChangedListener也被回调,所以这个时候把onClick时的view.isChecked当作旧的状态去使用,就会出错。记住这个时候已经是这次点击checked change生效后了。

使用onCheckedChangeListener代替onClickListener

可以代替使用,但需要注意,最好不要把响应点击的事件放在其中,因为如果有其他代码处会使用setChecked来改变check状态而不是用户触摸的话,只该被用户点击发生的事件也会发生。

建议:使用onCheckedChangeListener来监听checked状态,onClickListener来处理点击交互,此时注意上一点问题。

如果一定要代替使用,可以通过在onCheckedChangeListener内判断isPressed()来确定是否来自用户交互。

view.setOnCheckedChangeListener((v, checked) -> {
    if (v.isPressed()) {
        // 点击交互
    }
})

代替使用在Accessibility模式下的问题

因为无障碍模式下,用户交互不是直接点击,而是发送调用setChecked,此时如果使用了上述方法,因为没有pressed,那么checkChangeListener就不会得到回调,可能会有错误产生。

最佳实践

在onCheckedChangeListener内不做交互相关监听,只处理其他不可见逻辑;

在onClickListener内只处理需要响应交互的逻辑,将此时的checked状态作为刷新后状态使用。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值