Android 开发之Dialog中隐藏键盘的正确使用方法

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));
}

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android LocationManager获取经度与纬度等地理信息

    Android LocationManager获取经度与纬度等地理信息 利用LocationManager实现定位功能 1 实时更新经度,纬度 2 根据经度和纬度获取地理信息(比如:国家,街道等)(略过) MainActivity如下: package cc.bb; import java.util.Iterator; import java.util.List; import android.location.Location; import android.location.Location

  • Android ListView之setEmptyView正确使用方法

    Android ListView之setEmptyView正确使用方法 我们知道ListView组件提供了一个空数据是的视图设置方法setEmptyView,该方法存在一个诟病,就是空视图和listview组件要在一个Parent中,这个就不在此细说,下面说另一个问题,原因其实和前面那个问题同出一辙. 假如emptyView和listview在布局中,已经属于同一个parent,设置EmptyView的代码如下 private void setEmptyView(){ emptyTv.setTe

  • Android MeasureSpec的理解和源码的解析

    Android  MeasureSpec的理解和源码的解析 MeasureSpec的创建规则: 实例详解: package cc.ww; import android.view.View; import android.view.View.MeasureSpec; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; import android.widget.L

  • Android Intent调用 Uri的方法总结

    Android Intent调用 Uri的方法总结 //调用浏览器 Uri uri = Uri.parse(""); Intent it = new Intent(Intent.ACTION_VIEW,uri); startActivity(it); //显示某个坐标在地图上 Uri uri = Uri.parse("geo:38.899533,-77.036476"); Intent it = new Intent(Intent.Action_VIEW,uri);

  • Android 软键盘状态并隐藏输入法的实例

    Android 软键盘状态并隐藏输入法的实例 1 软键盘状态的切换 2 强制隐藏输入法键盘 MainActivity如下: package cc.c; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.inputmethod.InputMethodManager; import android.widget.Button

  • Android中Activity和Fragment传递数据的两种方式

    1.第一种方式,也是最常用的方式,就是使用Bundle来传递参数 MyFragment myFragment = new MyFragment(); Bundle bundle = new Bundle(); bundle.putString("DATA",values);//这里的values就是我们要传的值 myFragment.setArguments(bundle); 然后在Fragment中的onCreatView方法中,通过getArgments()方法,获取到bundle

  • 微信Android热更新Tinker使用详解(星空武哥)

    Tinker是什么 Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码.So库以及资源,让应用能够在不需要重新安装的情况下实现更新.当然,你也可以使用Tinker来更新你的插件. 它主要包括以下几个部分: gradle编译插件: tinker-patch-gradle-plugin 核心sdk库: tinker-android-lib 非gradle编译用户的命令行版本: tinker-patch-cli.jar 为什么使用Tinker 当前市面的热补丁方案有很多,其中比较

  • Android 开发之Dialog中隐藏键盘的正确使用方法

    Android 开发之Dialog中隐藏键盘的正确使用方法 场景:弹出一个Dialog,里面有一个EditText,用来输入内容,因为输入时,需要弹出键盘,所以当Dialog消失时,键盘要一起隐藏. 现在我们做一个自定义的Dialog MyDialog extends Dialog 一开始认为这个功能很容易实现,于是写了下面的代码 //Dialog的构造函数中写 this.setOnDismissListener(new OnDismissListener() { @Override publi

  • Android开发之ListView列表刷新和加载更多实现方法

    本文实例讲述了Android开发之ListView列表刷新和加载更多实现方法.分享给大家供大家参考.具体如下: 上下拉实现刷新和加载更多的ListView,如下: package com.sin.android.ui; import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import andro

  • Android开发之imageView图片按比例缩放的实现方法

    本文实例讲述了Android开发之imageView图片按比例缩放的实现方法.分享给大家供大家参考,具体如下: android:scaleType可控制图片的缩放方式,示例代码如下: <ImageView android:id="@+id/img" android:src=\'#\'" /logo" android:scaleType="centerInside" android:layout_width="60dip"

  • Android 开发之Dialog,Toast,Snackbar提醒

    今天给大家带来一篇简单易懂的微技巧文章,并没有什么高深的技术点,但重点是在细节,相信可以给不少朋友带来帮助. Dialog和Toast所有人肯定都不会陌生的,这个我们平时用的实在是太多了.而Snackbar是Design Support库中提供的新控件,有些朋友可能已经用过了,有些朋友可能还没去了解.但是你真的知道什么时候应该使用Dialog,什么时候应该使用Toast,什么时候应该使用Snackbar吗?先看效果图: 1,Dialog 首先来介绍一下Dialog的用法: AlertDialog

  • Android Dialog中软键盘的显示与隐藏的示例

    1.写在前面 本篇的主要内容是关于在Dialog中软键盘的显示与隐藏问题,需求是在Dialog中有一个密码输入框,弹出Dialog显示软键盘,关闭Dialog隐藏软键盘. 嗯,是不是有点简单,不过在实现的过程中还是遇到了一些问题,在试过了网上大部分的方法之后,最终找到了一个还不错的方法,分享给大家. 看下效果图: 2.实现过程 先说说最开始的实现方法: // 显示Dialog dialog.show(); // 显示软键盘 SoftInputUtils.showSoftInput(activit

  • Android编程开发之EditText中inputType属性小结

    本文总结分析了Android编程开发之EditText中inputType属性.分享给大家供大家参考,具体如下: android 1.5以后添加了软件虚拟键盘的功能,所以在输入提示中将会有对应的软键盘模式. android中inputType属性在EditText输入值时启动的虚拟键盘的风格有着重要的作用.这也大大的方便的操作.有时需要虚拟键盘只为字符或只为数字.所以inputType尤为重要. 复制代码 代码如下: <EditText android:layout_width="fill

  • Android编程开发之EditText中不输入特定字符会显示相关提示信息的方法

    本文实例讲述了Android编程开发之EditText中不输入特定字符会显示相关提示信息的方法.分享给大家供大家参考,具体如下: 先看效果图: 源码如下: 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="

  • Android开发之ListView的head消失页面导航栏的渐变出现和隐藏

    1.Fragment页面xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

  • Android开发之在xml中设置自定义属性的方法

    xml中设置自定义属性 分三步: 1. 在项目中的values文件中创建attrs文件 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="QLoadingIndicatorView"> <attr name="indicatorId" format="integer"

  • Android开发之ImageLoader使用详解

    先给大家展示效果图,看看是大家想要的效果吗,如果还满意,请参考以下代码: 前言 UniversalImageLoader是用于加载图片的一个开源项目,在其项目介绍中是这么写的, •支持多线程图片加载 •提供丰富的细节配置,比如线程池大小,HTPP请求项,内存和磁盘缓存,图片显示时的参数配置等等: •提供双缓存 •支持加载过程的监听: •提供图片的个性化显示配置接口: •Widget支持(这个,个人觉得没必要写进来,不过尊重原文) 其他类似的项目也有很多,但这个作为github上著名的开源项目被广

随机推荐