Android 软键盘控制方法以及开发中遇到的一些问题。转

怀抱观古今,寝食展戏谑。这篇文章主要讲述Android 软键盘控制方法以及开发中遇到的一些问题。转相关的知识,希望能为你提供帮助。
Android 提供了 windowSoftInputMode 属性来控制输入法软键盘窗口和 Activity 主窗口的交互,分为 窗口尺寸调整系列 和 输入法软键盘显示控制系列。
 
窗口尺寸调整系列:该系列参数用来控制当软键盘弹起时,Activity 主窗口的调整策略,因为如果不调整主窗口,很可能会导致当前输入的控件被软键盘遮挡。
adjustPan:
Activity的主窗口并不会重新调整大小来为输入法腾出空间,而是窗口的内容会自动上下晃动来保证当前获得焦点的控件不会被键盘遮挡住,然后用户可以看见自己输入的内容。相比于 adjustResize 模式而言,它并不是很令人满意,因为用户必须关闭输入法来和被输入法遮挡住的控件进行交互。
adjustResize:
Activity的主窗口会重新调整大小来为输入法腾出空间。
adjustUnspecified:
当前模式并不会明确指定 Activity 使用adjustPan 或者 adjustResize ,系统会自动选择一个模式,选择结果是,如果当前 Activity 的 Window 中,有可以滚动自身内容的控件,比如 ScrollView,那么选择结果就是 adjustResize,因为它认为滚动可以使 Window 中的内容即使在一个很小的区域中也可以被看见。Activity 的默认模式就是这个模式。
adjustNoting:
Activity 的 Window 没有任何变化。
  两种模式下,屏幕 - 主窗口 - 主窗口内容 - 软键盘 的关系如下:

Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
 
具体效果如下: 
没有滚动内容,adjustPan:
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
没有滚动内容,adjustResize:
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
没有滚动内容,adjustUnspecified == adjustPan
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
有滚动内容(ScrollView),adjustPan
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
有滚动内容(ScrollView),adjustResize
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

 
有滚动内容(ScrollView),adjustUnspecified == adjustResize
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

【Android 软键盘控制方法以及开发中遇到的一些问题。转】 
 
 
输入法软键盘显示控制系列:该系列参数用来控制当一个包含 Window 的事物(Activity、Dialog等)展示在屏幕最前端时,软键盘的显示或者隐藏策略。
stateUnspecified:
系统根据当前具体情况,选择相应的模式。
stateUnchanged:
软键盘保持它的上一个状态(上一个Activity 或者 Dialog 在屏幕最前端时,软键盘的状态),不做变化,不管上一个状态是显示还是隐藏。
stateHidden:
当用户主动进入当前界面时,软键盘隐藏。离开上一个 界面,返回当前界面,不能算作 “主动进入”。被动进入时,保持上一个状态。
stateAlwaysHidden:
只要是用户进入该界面,就隐藏软键盘,不管是主动进入(新启动该界面),还是被动进入(离开上一个界面,返回到当前界面)。
stateVisible:
当用户主动进入当前界面时,显示软键盘。离开上一个 界面,返回当前界面,不能算作 “主动进入”。被动进入时,保持上一个状态。
stateAlwaysVisible:
只要是用户进入该界面,就显示软键盘,不管是主动进入(新启动该界面),还是被动进入(离开上一个界面,返回到当前界面)。
 
 
 
关于某些华为手机的一个Bug 
今天遇到一个Bug,是这样的,在某些华为手机上面,除了第一次点击输入框,adjustPan 参数会生效(软键盘可以正常弹起输入框),后面从第二次开始,怎么点击,adjustPan 参数都无效。
布局模型大致如下:
[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. < RelativeLayout   
  2.         xmlns:android="http://schemas.android.com/apk/res/android"   
  3.         xmlns:tools="http://schemas.android.com/tools"   
  4.         android:id="@+id/activity_main"   
  5.         android:layout_width="match_parent"   
  6.         android:layout_height="match_parent"   
  7.         tools:context="cn.hjf.inputtest.MainActivity">    
  8.    
  9.         < ScrollView   
  10.                 android:layout_width="match_parent"   
  11.                 android:layout_height="match_parent">    
  12.    
  13.                 < LinearLayout   
  14.                         android:layout_width="match_parent"   
  15.                         android:layout_height="match_parent"   
  16.                         android:orientation="vertical">    
  17.    
  18.                         < View   
  19.                                 android:layout_width="match_parent"   
  20.                                 android:layout_height="400dp"   
  21.                                 android:background="#2b532b"/>    
  22.    
  23.                         < EditText   
  24.                                 android:layout_width="90dp"   
  25.                                 android:layout_height="wrap_content"   
  26.                                 android:layout_gravity="center_vertical"   
  27.                                 android:background="@null"   
  28.                                 android:gravity="center"   
  29.                                 android:inputType="numberDecimal"   
  30.                                 android:maxLength="8"   
  31.                                 android:minWidth="60dp"   
  32.                                 android:padding="5dp"   
  33.                                 android:text="0.00"/>    
  34.    
  35.                 < /LinearLayout>    
  36.    
  37.         < /ScrollView>    
  38.    
  39. < /RelativeLayout>    
 
效果是这样的:
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片


经过漫长时间的排除(很辛苦),终于找到了Bug的触发临界点,就是下面这两句话:
[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. android:gravity="center"   
  2. android:inputType="numberDecimal"   
又经过了漫长时间的验证,得出一个结论:在某些华为机型上面,在这种布局模型下,EditText 中如果设置了 inputType 参数(不为 none),那么,在 gravity 取值为某些值得时候,会导致该问题的发生。大致情况如下:
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片


红色表示失效,绿色表示有效(可以正常工作)。当这两个参数不指定的时候,可以工作,因为这两个属性默认值的组合是可以工作的,上图中的蓝色块。(备注:没有完全匹配所有情况,如有相似情况,可以按需匹配,查看结果)
 
在源码中可以找到这两个属性的默认值:
  attrs.xml

[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. < !--  Default  EditText  style.  -->    
  2.               < attr  name="editTextStyle"  format="reference"  />      
themes.xml
[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. < item  name="editTextStyle"> @style/Widget.EditText< /item>    
  styles.xml
[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. < style  name="Widget.EditText">    
  2.                 < item  name="focusable"> true< /item>    
  3.                 < item  name="focusableInTouchMode"> true< /item>    
  4.                 < item  name="clickable"> true< /item>    
  5.                 < item  name="background"> ?attr/editTextBackground< /item>    
  6.                 < item  name="textAppearance"> ?attr/textAppearanceMediumInverse< /item>    
  7.                 < item  name="textColor"> ?attr/editTextColor< /item>    
  8.                 < item  name="gravity"> center_vertical< /item>    
  9.                 < item  name="breakStrategy"> simple< /item>    
  10.                 < item  name="hyphenationFrequency"> normal< /item>    
  11.         < /style>    
  12.      
attrs.xml

[html] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1.   < !--  The  type  of  data  being  placed  in  a  text  field,  used  to  help  an   
  2.                   input  method  decide  how  to  let  the  user  enter  text.    The  constants   
  3.                   here  correspond  to  those  defined  by   
  4.                   {@link  android.text.InputType}.    Generally  you  can  select   
  5.                   a  single  value,  though  some  can  be  combined  together  as   
  6.                   indicated.    Setting  this  attribute  to  anything  besides   
  7.                   < var> none< /var>   also  implies  that  the  text  is  editable.  -->    
  8.         < attr  name="inputType">    
  9.                 < !--  There  is  no  content  type.    The  text  is  not  editable.  -->    
  10.                 < flag  name="none"  value="https://www.songbingjia.com/android/0x00000000"  />    
  11. ..........   
  12.      
[java] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1.   /** 
  2.   *  Special  content  type  for  when  no  explicit  type  has  been  specified. 
  3.   *  This  should  be  interpreted  to  mean  that  the  target  input  connection 
  4.   *  is  not  rich,  it  can  not  process  and  show  things  like  candidate  text  nor 
  5.   *  retrieve  the  current  text,  so  the  input  method  will  need  to  run  in  a 
  6.   *  limited  "generate  key  events"  mode,  if  it  supports  it.  Note  that  some 
  7.   *  input  methods  may  not  support  it,  for  example  a  voice-based  input 
  8.   *  method  will  likely  not  be  able  to  generate  key  events  even  if  this 
  9.   *  flag  is  set. 
  10.   */   
  11. public  static  final  int  TYPE_NULL  =  0x00000000;    
 
 
 
一个需求遇到一个需求,大致模型为:有一个界面,里面有一个 输入框 和 两个按钮,分别控制输入框中数字的加减,如下图所示:
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片

每次输入框数字变化,不管是手动输入还是按钮控制,都会出发刷新工作,刷新时会弹出一个对话框。
然后需求是这样的,当手动输入的时候,这时触发刷新时,输入法是显示的,但是对话框显示然后消失后,输入法就被隐藏了。当用按钮控制的时候,是没问题的,因为整个过程,输入法都是隐藏的。所以需求就是,在对话框显示然后消失后,输入法能保持出发刷新时的状态。
 
解决问题:当把当前 Activity 设置为 stateUnchanged 的时候,并没有达到理想的效果,因为dialog所在的window,没有设置该属性,所以需要把dialog的window也设置为stateUnchanged,方法为:
[java] view plain copy
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
Android 软键盘控制方法以及开发中遇到的一些问题。转

文章图片
  1. getWindow().setSoftInputMode()   

然后就可以了。







    推荐阅读