Android Dialog与软键盘的正确打开方式

来源:互联网 发布:华为面试常见算法题 编辑:程序博客网 时间:2024/05/28 22:12

1.写在前面

2017年的第一篇博客,首先祝大家新年快乐,在新的一年里健健康康、平平安安!

本篇博客的主要内容是关于在Dialog中软键盘的显示与隐藏问题,需求是在Dialog中有一个密码输入框,弹出Dialog显示软键盘,关闭Dialog隐藏软键盘。
嗯,是不是有点简单,不过在实现的过程中还是遇到了一些问题,在试过了网上大部分的方法之后,最终找到了一个还不错的方法,分享给大家。

看下效果图:

Dialog

2.实现过程

先说说最开始的实现方法:

// 显示Dialogdialog.show();// 显示软键盘SoftInputUtils.showSoftInput(activity);

But,软键盘并没有显示,显示软键盘有两种方法,使用的是第一种方法,第二种方法在Dialog中没有效果。

// 第一种,如果软键盘在窗口上已经显示,则隐藏,反之则显示InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);// 第二种,强制显示软键盘,view为当前的输入框对象inputMethodManager.showSoftInput(view,InputMethodManager.SHOW_FORCED);  

于是查看Dialog的源码,发现Dialog的显示和隐藏是通过Handler来处理的,会不会是显示软键盘的方法执行的太快了,于是在show方法后延时显示软键盘,发现是可以正常显示的。
但是延时处理这种方法显然不太好,有没有一种Dialog显示完成后就能回调的方法呢,嗯,有的,setOnShowListener方法,在OnShowListener接口的回调方法onShow中显示软键盘就可以了。软键盘的隐藏并没有这些限制,在dismiss之后隐藏,或者在回调方法onDismiss中隐藏都可以。

/** * 发送显示Dialog的消息 */private void sendShowMessage() {    if (mShowMessage != null) {        // Obtain a new message so this dialog can be re-used        Message.obtain(mShowMessage).sendToTarget();    }}/** * 接收显示或隐藏Dialog的消息 */private static final class ListenersHandler extends Handler {    private WeakReference<DialogInterface> mDialog;    public ListenersHandler(Dialog dialog) {        mDialog = new WeakReference<DialogInterface>(dialog);    }    @Override    public void handleMessage(Message msg) {        switch (msg.what) {            case DISMISS:                ((OnDismissListener) msg.obj).onDismiss(mDialog.get());                break;            case CANCEL:                ((OnCancelListener) msg.obj).onCancel(mDialog.get());                break;            case SHOW:                ((OnShowListener) msg.obj).onShow(mDialog.get());                break;        }    }}

延时显示软键盘

new Thread() {    @Override    public void run() {        super.run();        activity.runOnUiThread(new Runnable() {            @Override            public void run() {                SoftInputUtils.showSoftInput(activity);            }        });    }}.start();

3.代码

显示Dialog提示框

public class DialogUtils {    private static Dialog dialog;    /**     * Dialog提示框消失方法     */    public static void dialogDismiss() {        if (isDialogShowing()) {            dialog.dismiss();            dialog = null;        }    }    /**     * Dialog提示框是否正在运行     *     * @return Dialog提示框是否正在运行     */    public static boolean isDialogShowing() {        return dialog != null && dialog.isShowing();    }    /**     * 创建Dialog提示框     *     * @param context 上下文     */    private static void createDialog(Context context) {        dialogDismiss();        dialog = new Dialog(context, R.style.SampleTheme);        dialog.setContentView(R.layout.layout_dialog);        // 点击弹窗外区域,弹窗不消失        dialog.setCanceledOnTouchOutside(false);    }    /**     * 显示确认安全码提示框     *     * @param activity              当前Activity     * @param dialogOnClickListener 确定按钮点击事件     */    public static void showSecurityCodeInputDialog(final Activity activity,                                                   final DialogOnClickListener dialogOnClickListener) {        createDialog(activity);        ImageView ivClose = (ImageView) dialog.findViewById(R.id.iv_close);        final GridPasswordView gpvCode = (GridPasswordView) dialog.findViewById(R.id.gpv_code);        Button btnOk = (Button) dialog.findViewById(R.id.btn_ok);        ivClose.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dialogDismiss();            }        });        btnOk.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String code = gpvCode.getPassWord();                dialogOnClickListener.onClick(code);            }        });        dialog.setOnShowListener(new DialogInterface.OnShowListener() {            @Override            public void onShow(DialogInterface dialog) {                // 获取焦点                gpvCode.requestFocus();                // 显示软键盘                SoftInputUtils.showSoftInput(activity);            }        });        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {            @Override            public void onDismiss(DialogInterface dialog) {                // 隐藏软键盘                SoftInputUtils.hideSoftInput(activity);            }        });        dialog.show();    }    public interface DialogOnClickListener {        /**         * 点击事件         *         * @param str 回调参数         */        public void onClick(String str);    }}

显示和隐藏软键盘的方法

public class SoftInputUtils {    /**     * 显示软键盘,Dialog使用     *     * @param activity 当前Activity     */    public static void showSoftInput(Activity activity) {        InputMethodManager inputMethodManager =                (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);        inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);    }    /**     * 隐藏软键盘     *     * @param activity 当前Activity     */    public static void hideSoftInput(Activity activity) {        InputMethodManager inputMethodManager =                (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);        inputMethodManager.hideSoftInputFromWindow(                activity.getWindow().getDecorView().getWindowToken(), 0);    }}

调用显示Dialog的方法

DialogUtils.showSecurityCodeInputDialog(this, new DialogUtils.DialogOnClickListener() {    @Override    public void onClick(String str) {        Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();        DialogUtils.dialogDismiss();    }});

4.写在最后

在频繁的显示、关闭Dialog的测试中发现,有时软键盘不会显示,但是没有找到规律,有了解的同学可以给我留言评论。

欢迎同学们吐槽评论,如果你觉得本篇博客对你有用,那么就留个言或者顶一下吧(^-^)

完整的Demo下载

2 0