禁用AlertDialog的按键

1

有时候我们需要禁用AlertDialog的按键。

一般情况下我们会利用AlertDialog的getButton接口获取到对应的Button,
然后调用Button的setEnabled接口,例如:

................
alertDialog.show();
alertDialog.getButton(
        AlertDialog.BUTTON_POSITIVE).setEnabled(false);
................

注意这里有个限制,就是必须等到AlertDialog调用show接口后,
才能获取到Button对象,对应的分析可以参考链接


2

除了上述方法外,是否还有其它方法可以在AlertDialog显示时禁用其按键呢?
答案是利用AlertDialog父类Dialog中的setOnShowListener接口。
其用法类似于:

...........
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
//可进行一些设置
...........

//创建出AlertDialog
AlertDialog alertDialog = alertBuilder.create();

//设置OnShowListener
alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
    //AlertDialog显示后,就会立马回调OnShowListener的onShow接口
    @Override
    public void onShow(DialogInterface dialog) {
        //dialog就是创建出的dialog
        ((AlertDialog)dialog).getButton(
                AlertDialog.BUTTON_POSITIVE).setEnabled(false);
    }
});

//alertBuilder.show(); 不要这样
alertDialog.show();
............

setOnShowListener接口的用法还是很简单的,但也有两个需要注意的地方。

2.1

setOnShowListener必须在AlertDialog调用show接口之前设置,否则不会进行回调。
这里实现的不是一种粘性(sticky)的回调策略。

我们看看源码中Dialog的setOnShowListener接口:

    ............
    public void setOnShowListener(@Nullable OnShowListener listener) {
        if (listener != null) {
            //注意,只是创建了一个Message
            mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
        } else {
            //默认是null
            mShowMessage = null;
        }
    }
    .............

再来看看Dialog的show接口:

public void show() {
    if (mShowing) {
        ...........
        return;
    }
    //组件等的创建
    ...........
    mWindowManager.addView(mDecor, l);
    mShowing = true;

    sendShowMessage();
}

private void sendShowMessage() {
    if (mShowMessage != null) {
        // Obtain a new message so this dialog can be re-used
        //发送消息给ListenersHandler,回调Listener的接口
        Message.obtain(mShowMessage).sendToTarget();
    }
}

由于sendShowMessage函数,只有在AlertDialog调用show的时候才会被调用。
因此如果在show之前,没有注册OnShowListener生成mShowMessage,
却在show后注册OnShowListener,该Listener并不会被回调。

2.2

调用AlertDialog.Builder的create接口创建AlertDialog后,
如果在该AlertDialog上设置Listener,就必须在该AlertDialog上调用show接口。
不能再使用AlertDialog.Builder的show接口。

我们看看源码就知道原因:

public AlertDialog show() {
    //重新创建出一个新的dialog
    final AlertDialog dialog = create();
    //然后show
    dialog.show();
    return dialog;
}

因此,如果在create接口创建出的dialog上增加Listener,
然后调用AlertDialog.Builder的show接口,那么之前的Listener不会被回调。
因为create接口创建出的dialog压根没被用到。

这个问题的原理很简单,但不注意的话还是会忽视的,
自己解bug时就发现过这个问题,好像是MTK写的代码(非黑)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值