`

Android不让弹出键盘挡住View

 
阅读更多

The AndroidManifest.xml File

<activity android:windowSoftInputMode=["stateUnspecified",

"stateUnchanged", "stateHidden",

"stateAlwaysHidden", "stateVisible",

"stateAlwaysVisible", "adjustUnspecified",

"adjustResize", "adjustPan"] …… >

</activity>

attributes:

android:windowSoftInputMode

活动的主窗口如何与包含屏幕上的软键盘窗口交互。这个属性的设置将会影响两件事情:

1>软键盘的状态——是否它是隐藏或显示——当活动(Activity)成为用户关注的焦点。

2>活动的主窗口调整——是否减少活动主窗口大小以便腾出空间放软键盘或是否当活动窗口的部分被软键盘覆盖时它的内容的当前焦点是可见的。

它的设置必须是下面列表中的一个值,或一个”state…”值加一个”adjust…”值的组合。在任一组设置多个值——多个”state…”values,例如&mdash有未定义的结果。各个值之间用|分开。例如: <activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >

在这设置的值("stateUnspecified""adjustUnspecified"以外)将覆盖在主题中设置的值

描述

"stateUnspecified"

软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。

这个是为了软件盘行为默认的设置。

"stateUnchanged"

软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。

"stateHidden"

当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity

"stateAlwaysHidden"

软键盘总是被隐藏的,当该Activity主窗口获取焦点时。

"stateVisible"

软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)

"stateAlwaysVisible"

当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity

"adjustUnspecified"

它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。

"adjustResize"

Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间

"adjustPan"

Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。





一、软键盘显示的原理
软件盘的本质是什么?软键盘其实是一个Dialog!
InputMethodService为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统对活动主窗口进行调整,从而为输入法腾出相应的空间,然后将该Dialog显示在底部,或者全屏显示。
二、活动主窗口调整
android定义了一个属性,名字为windowSoftInputMode, 用它可以让程序可以控制活动主窗口调整的方式。我们可以在AndroidManifet.xml中对Activity进行设置。如:android:windowSoftInputMode="stateUnchanged|adjustPan"
该属性可选的值有两部分,一部分为软键盘的状态控制,另一部分是活动主窗口的调整。前一部分本文不做讨论,请读者自行查阅android文档。
模式一,压缩模式
windowSoftInputMode的值如果设置为adjustResize,那么该Activity主窗口总是被调整大小以便留出软键盘的空间。
我们通过一段代码来测试一下,当我们设置了该属性后,弹出输入法时,系统做了什么。
重写Layout布局:

  1. publicclassResizeLayoutextendsLinearLayout{
  2. privatestaticintcount=0;
  3. publicResizeLayout(Contextcontext,AttributeSetattrs){
  4. super(context,attrs);
  5. }
  6. @Override
  7. protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){
  8. super.onSizeChanged(w,h,oldw,oldh);
  9. Log.e("onSizeChanged"+count++,"=>onResizecalled!w="+w+",h="+h+",oldw="+oldw+",oldh="+oldh);
  10. }
  11. @Override
  12. protectedvoidonLayout(booleanchanged,intl,intt,intr,intb){
  13. super.onLayout(changed,l,t,r,b);
  14. Log.e("onLayout"+count++,"=>OnLayoutcalled!l="+l+",t="+t+",r="+r+",b="+b);
  15. }
  16. @Override
  17. protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
  18. super.onMeasure(widthMeasureSpec,heightMeasureSpec);
  19. Log.e("onMeasure"+count++,"=>onMeasurecalled!widthMeasureSpec="+widthMeasureSpec+",heightMeasureSpec="+heightMeasureSpec);
  20. }

我们的布局设置为:

  1. <com.winuxxan.inputMethodTest.ResizeLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/root_layout"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical"
  7. >
  8. <EditText
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content"
  11. />
  12. <LinearLayout
  13. android:id="@+id/bottom_layout"
  14. android:layout_width="fill_parent"
  15. android:layout_height="fill_parent"
  16. android:orientation="vertical"
  17. android:gravity="bottom">s
  18. <TextView
  19. android:layout_width="fill_parent"
  20. android:layout_height="wrap_content"
  21. android:text="@string/hello"
  22. android:background="#77777777"
  23. />
  24. </LinearLayout>
  25. </com.winuxxan.inputMethodTest.ResizeLayout>

AndroidManifest.xml的Activity设置属性:android:windowSoftInputMode = "adjustResize"
运行程序,点击文本框,查看调试信息:
E/onMeasure 6(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742024
E/onMeasure 7(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742025
E/onSizeChanged 8(7960): =>onSizeChanged called! w=320,h=201,oldw=320,oldh=377
E/onLayout 9(7960): =>OnLayout called! l=0, t=0,r=320,b=201
从调试结果我们可以看出,当我们点击文本框后,根布局调用了onMeasure,onSizeChanged和onLayout。
实际上,当设置为adjustResize后,软键盘弹出时,要对主窗口布局重新进行measure和layout,而在layout时,发现窗口的大小发生的变化,因此调用了onSizeChanged。
从下图的运行结果我们也可以看出,原本在下方的TextView被顶到了输入法的上方。

模式二,平移模式
windowSoftInputMode的值如果设置为adjustPan,那么该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
上面的例子中,我们将AndroidManifest.xml的属性进行更改:android: windowSoftInputMode = "adjustPan"

重新运行,并点击文本框,查看调试信息:
E/onMeasure 6(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742200
E/onMeasure 7(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742201
E/onLayout 8(8378): =>OnLayout called! l=0, t=0,r=320,b=377
我们看到:系统也重新进行了measrue和layout,但是我们发现,layout过程中onSizeChanged并没有调用,这说明输入法弹出前后并没有改变原有布局的大小。
从下图的运行结果我们可以看到,下方的TextView并没有被顶到输入法上方。

事实上,当输入框不会被遮挡时,该模式没有对布局进行调整,然而当输入框将要被遮挡时,窗口就会进行平移。也就是说,该模式始终是保持输入框为可见。如下图,整个窗口,包括标题栏均被上移,以保证文本框可见。

模式三 自动模式
当属性windowSoftInputMode被设置为adjustUspecified时,它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。
也就是说,系统自动决定是采用平移模式还是压缩模式,决定因素在于内容是否可以滚动。

三、侦听软键盘的显示隐藏
有时候,借助系统本身的机制来实现主窗口的调整并非我们想要的结果,我们可能希望在软键盘显示隐藏的时候,手动的对布局进行修改,以便使软键盘弹出时更加美观。这时就需要对软键盘的显示隐藏进行侦听。
直接对软键盘的显示隐藏侦听的方法本人没有找到,如果哪位找到的方法请务必告诉本人一声。还有本方法针对压缩模式,平移模式不一定有效。
我们可以借助软键盘显示和隐藏时,对主窗口进行了重新布局这个特性来进行侦听。如果我们设置的模式为压缩模式,那么我们可以对布局的onSizeChanged函数进行跟踪,如果为平移模式,那么该函数可能不会被调用。
我们可以重写根布局,因为根布局的高度一般情况下是不发生变化的。
假设跟布局为线性布局,模式为压缩模式,我们写一个例子,当输入法弹出时隐藏某个view,输入法隐藏时显示某个view。

  1. publicclassResizeLayoutextendsLinearLayout{
  2. privateOnResizeListenermListener;
  3. publicinterfaceOnResizeListener{
  4. voidOnResize(intw,inth,intoldw,intoldh);
  5. }
  6. publicvoidsetOnResizeListener(OnResizeListenerl){
  7. mListener=l;
  8. }
  9. publicResizeLayout(Contextcontext,AttributeSetattrs){
  10. super(context,attrs);
  11. }
  12. @Override
  13. protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){
  14. super.onSizeChanged(w,h,oldw,oldh);
  15. if(mListener!=null){
  16. mListener.OnResize(w,h,oldw,oldh);
  17. }
  18. }
  19. }

在我们的Activity中,通过如下方法调用:

  1. publicclassInputMethodTestActivityextendsActivity{
  2. privatestaticfinalintBIGGER=1;
  3. privatestaticfinalintSMALLER=2;
  4. privatestaticfinalintMSG_RESIZE=1;
  5. privatestaticfinalintHEIGHT_THREADHOLD=30;
  6. classInputHandlerextendsHandler{
  7. @Override
  8. publicvoidhandleMessage(Messagemsg){
  9. switch(msg.what){
  10. caseMSG_RESIZE:{
  11. if(msg.arg1==BIGGER){
  12. findViewById(R.id.bottom_layout).setVisibility(View.VISIBLE);
  13. }else{
  14. findViewById(R.id.bottom_layout).setVisibility(View.GONE);
  15. }
  16. }
  17. break;
  18. default:
  19. break;
  20. }
  21. super.handleMessage(msg);
  22. }
  23. }
  24. privateInputHandlermHandler=newInputHandler();
  25. /**Calledwhentheactivityisfirstcreated.*/
  26. @Override
  27. publicvoidonCreate(BundlesavedInstanceState){
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.main);
  30. ResizeLayoutlayout=(ResizeLayout)findViewById(R.id.root_layout);
  31. layout.setOnResizeListener(newResizeLayout.OnResizeListener(){
  32. publicvoidOnResize(intw,inth,intoldw,intoldh){
  33. intchange=BIGGER;
  34. if(h<oldh){
  35. change=SMALLER;
  36. }
  37. Messagemsg=newMessage();
  38. msg.what=1;
  39. msg.arg1=change;
  40. mHandler.sendMessage(msg);
  41. }
  42. });
  43. }
  44. }

这里特别需要注意的是,不能直接在OnResizeListener中对要改变的View进行更改,因为OnSizeChanged函数实际上是运行在View的layout方法中,如果直接在onSizeChange中改变view的显示属性,那么很可能需要重新调用layout方法才能显示正确。然而我们的方法又是在layout中调用的,因此会出现错误。因此我们在例子中采用了Handler的方法。


分享到:
评论

相关推荐

    知识共享-Android不让弹出键盘挡住View(雷惊风).

    ### Android不让弹出键盘挡住View:深入解析与实践 #### 软键盘显示原理与机制 在探讨如何防止Android弹出键盘遮挡View之前,我们首先需要理解软键盘的显示原理。软键盘并非简单的界面元素,实际上,它是由`...

    Android 设置一个底部控件view随着软键盘的弹出而上移

    有一些开源库,如`android-useful-dialogs`和`android-keyboard-aware-scroll-view`,已经实现了键盘弹出时底部视图上移的功能。可以直接集成这些库,简化开发过程。 在"Android 底部控件随软键盘弹出demo"这个...

    android 自定义View于弹出软键盘之上

    软键盘弹出之后,计算软键盘的高度,将自定义的View设置于软键盘之上。代码重点计算了如何让软键盘显示与隐藏,并且,还解决了如何点击软键盘与自定义View 之外的区域,让软键盘隐藏而不会与其他控件的点击事件冲突...

    android 输入法键盘弹出与否判断和输入法键盘弹出时将界面滚动到指定位置demo

    这个"android 输入法键盘弹出与否判断和输入法键盘弹出时将界面滚动到指定位置demo"着重于解决两个关键问题:一是检测输入法键盘是否弹出,二是当键盘弹出时如何自动调整界面布局以确保重要内容可见。 首先,我们要...

    Android判断软键盘是否弹出

    在Android开发中,有时我们需要检测应用中的软键盘是否弹出,以便进行相应的界面调整或功能控制。例如,当用户打开虚拟键盘时,我们可能需要自动调整输入框的位置,或者在键盘隐藏时恢复原来的布局。标题“Android...

    android EditText跟随键盘弹出,背景不会被顶上去

    3. **使用第三方库**:如`android-useful-dialogs`或`android-keyboard-aware-scroll-view`等库,它们已经封装了处理键盘弹出的功能,可以简化开发过程。只需引入依赖并按照库的文档进行配置,即可实现`EditText`...

    5种方法完美解决android软键盘挡住输入框方法详解

    在Android应用开发中,经常会遇到一个问题,即当用户在输入框中输入时,弹出的软键盘会遮挡部分屏幕内容,尤其是对于登录或注册等需要填写多项信息的界面,这种情况严重影响了用户体验。为了解决这个问题,Android...

    EditText跟随键盘弹出,背景不动

    在Android开发中,"EditText跟随键盘弹出,背景不动"是一个常见的用户界面需求,尤其是在创建输入表单或者聊天应用时。这个现象涉及到Android系统的行为、布局管理器以及自定义视图处理。以下将详细讲解相关的知识点...

    datepickerdialog禁止自动弹出键盘

    当我们使用`DatePickerDialog`时,有时会遇到一个常见问题:当对话框显示时,系统默认可能会自动弹出软键盘,这可能不符合某些应用的设计需求,比如用户在特定场景下不需要手动输入日期,或者希望保持屏幕空间用于...

    android中监听软键盘的弹出与隐藏,并获取软键盘的高度

    总的来说,监听Android软键盘的弹出与隐藏,以及获取软键盘高度,可以通过多种方式实现,开发者应根据具体需求选择合适的方法。同时,要注意兼容不同的`windowSoftInputMode`设置,以确保在各种情况下都能正确处理...

    禁止软键盘弹出,自定义键盘

    在移动设备上,软键盘是用户输入文本的常见方式,但在某些特定场景下,例如游戏、全屏应用或自定义输入界面,我们可能需要禁止软键盘自动弹出,并且使用自定义键盘来替代。本教程将详细介绍如何实现这一功能。 首先...

    Android中长按弹出选项框View进行操作

    本教程将详细讲解如何在Android应用中实现长按View弹出选项框的功能。 首先,你需要创建一个`PopupMenu`对象。`PopupMenu`类是Android SDK提供的用于创建弹出菜单的工具。在长按事件的监听器中实例化这个对象: ``...

    android 监听软键盘状态(弹起还是收起)

    下面将详细介绍如何在Android应用中监听软键盘的弹起与收起。 首先,我们需要理解Android布局高度的变化。当软键盘弹起时,屏幕可用的高度会减少,因为一部分空间被键盘占用;而当软键盘收起时,屏幕高度将恢复到...

    android ListView中EditText被选中时弹出键盘会丢失EditText的焦点

    // 不拦截触摸事件,让子View处理 } } ``` 3. **使用Adapter的getViewTypeCount和getItemViewType**:如果ListView中有多种类型的视图,可以通过这两个方法区分EditText所在的视图,确保它们不会被错误地复用。 ...

    android 软键盘弹出相关的坑之解决方法

    在Android开发中,软键盘的弹出与隐藏问题常常给开发者带来困扰,尤其是在全屏模式和非全屏模式下。本文将深入探讨这些"坑"并提供相应的解决方法。 首先,我们来理解软键盘弹出的基本原理。Android系统在用户点击...

    监听软键盘的弹出与收起

    在Android开发中,软键盘的弹出与收起是一个常见的交互事件,对于界面布局和用户体验有着重要影响。本文将深入探讨如何在Android应用中监听软键盘的弹出与收起,以及实现这一功能的一些关键技术和策略。 首先,软...

    android 自定义AlertDialog弹出键盘可以输入的

    此外,为了让键盘在`AlertDialog`弹出时自动显示,我们需要在`AndroidManifest.xml`中为对应的Activity添加以下属性: ```xml android:name=".YourActivity" android:windowSoftInputMode="adjustPan"&gt; ``` `...

    Android禁止EditText自动弹出软键盘的方法及遇到问题

    Android 禁止 EditText 自动弹出软键盘的方法及遇到问题 Android 中,EditText 是一个非常常用的控件,它可以让用户输入文本信息。但是,在某些情况下,我们可能不希望 EditText 自动弹出软键盘,例如在一些特定的...

    Android 解决软键盘遮挡登陆按钮

    然而,当软键盘弹出时,布局不会自动适应键盘的高度,因此可能导致下方元素被遮挡。 解决软键盘遮挡登录按钮的方法主要有以下几种: 1. 使用`android:windowSoftInputMode="adjustResize"`: 在AndroidManifest....

    editview软键盘自动弹出和隐藏

    在Android开发中,EditView是用户输入文本的常见组件,当用户点击EditView时,系统默认行为是自动弹出软键盘以便用户输入。在某些情况下,我们可能希望自定义这一行为,例如,当我们想要在应用启动时就显示软键盘,...

Global site tag (gtag.js) - Google Analytics