Android 开发之Dialog中隐藏键盘的正确使用方法
发布时间 - 2026-01-11 03:05:06 点击率:次Android 开发之Dialog中隐藏键盘的正确使用方法

场景:弹出一个Dialog,里面有一个EditText,用来输入内容,因为输入时,需要弹出键盘,所以当Dialog消失时,键盘要一起隐藏。
现在我们做一个自定义的Dialog
MyDialog extends Dialog
一开始认为这个功能很容易实现,于是写了下面的代码
//Dialog的构造函数中写
this.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
hideKeyBoard();
}
});
//edContent是输入框
public void hideKeyBoard(){
InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(edContent.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
运行之后,发现根本无法隐藏,看看hideSoftInputFromWindow中干了啥
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
checkFocus();
synchronized (mH) {
if (mServedView == null || mServedView.getWindowToken() != windowToken) {
return false;
}
try {
return mService.hideSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
}
return false;
}
}
跟踪进去发现参数 windowToken 是 null,而且 mServedView 也是null,所以直接返回false,无法隐藏。
也就是说,你监听Cancel或者Dismiss都是不行的,因为此时Dialog已经消失,用于输入的服务窗体已经是null了,所以你要想 隐藏键盘,就需要在Dismiss之前处理,那这个入口在哪呢?
为了当点击空白处时,可以隐藏Dialog,所以我们在构造函数中加了一句话
this.setCanceledOnTouchOutside(true);
所以当我们点击空白区域时,会触发Dialog的onTouchEvent
public boolean onTouchEvent(MotionEvent event) {
if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
cancel();
return true;
}
return false;
}
这里会调用基类Window的shouldCloseOnTouch方法,来判断是否可以关闭,这里我们看到如果满足,就直接cancel()了,
public void cancel() {
if (!mCanceled && mCancelMessage != null) {
mCanceled = true;
// Obtain a new message so this dialog can be re-used
Message.obtain(mCancelMessage).sendToTarget();
}
dismiss();
}
这里面就会dismiss掉Dialog,所以我们发现,在dismiss前,我们根本无法干预,真是个悲剧。所以我们只能重载onTouchEvent方法,并且自己判断是否可以关闭(也就是把下面代码迁移到你的代码中!
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(context, event) && peekDecorView() != null) {
return true;
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
自己代码中这样
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isShowing() && shouldCloseOnTouch(getContext(),event)){
hideKeyBoard();
}
return super.onTouchEvent(event);
}
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN
&& isOutOfBounds(context, event) && getWindow().peekDecorView() != null) {
return true;
}
return false;
}
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
final View decorView = getWindow().getDecorView();
return (x < -slop) || (y < -slop)
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Android
# Dialog中隐藏键盘
# Dialog中隐藏键盘的实现方法
# Android中AlertDialog 点击按钮后不关闭对话框的功能
# Android dialog 去除虚拟按键的解决方法
# 弹出
# 都是
# 判断是否
# 就会
# 是个
# 如有
# 很容易
# 希望能
# 要想
# 做一个
# 写了
# 自定义
# 当我们
# 句话
# 干了
# 谢谢大家
# 这里面
# 输入框
# 有一个
# 中加
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
zabbix利用python脚本发送报警邮件的方法
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
制作旅游网站html,怎样注册旅游网站?
Python文件操作最佳实践_稳定性说明【指导】
Laravel怎么调用外部API_Laravel Http Client客户端使用
Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】
Laravel事件监听器怎么写_Laravel Event和Listener使用教程
简历在线制作网站免费版,如何创建个人简历?
Laravel定时任务怎么设置_Laravel Crontab调度器配置
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】
如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环
怎样使用JSON进行数据交换_它有什么限制
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
如何用腾讯建站主机快速创建免费网站?
电商网站制作价格怎么算,网上拍卖流程以及规则?
如何在云主机上快速搭建多站点网站?
JavaScript如何操作视频_媒体API怎么控制播放
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
Laravel怎么清理缓存_Laravel optimize clear命令详解
如何用IIS7快速搭建并优化网站站点?
如何在腾讯云免费申请建站?
Laravel Docker环境搭建教程_Laravel Sail使用指南
佛山网站制作系统,佛山企业变更地址网上办理步骤?
JS经典正则表达式笔试题汇总
Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程
Laravel如何配置和使用缓存?(Redis代码示例)
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
Android 常见的图片加载框架详细介绍
如何快速搭建高效香港服务器网站?
佛山企业网站制作公司有哪些,沟通100网上服务官网?
Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
三星网站视频制作教程下载,三星w23网页如何全屏?
javascript中的try catch异常捕获机制用法分析
微信小程序 input输入框控件详解及实例(多种示例)
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
香港服务器建站指南:免备案优势与SEO优化技巧全解析
开心动漫网站制作软件下载,十分开心动画为何停播?
JavaScript中的标签模板是什么_它如何扩展字符串功能
如何挑选优质建站一级代理提升网站排名?
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
在centOS 7安装mysql 5.7的详细教程
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
装修招标网站设计制作流程,装修招标流程?
Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】

