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

在开发中,经常会遇到键盘挡住输入框的情况,比如登录界面或注册界面,弹出的软键盘把登录或注册按钮挡住了,用户必须把软键盘收起,才能点击相应按钮,这样的用户体验非常不好。像微信则直接把登录按钮做在输入框的上面,但有很多情况下,这经常满足不了需求。同时如果输入框特别多的情况下,点击输入时,当前输入框没被挡住,但是当前输入框下面的输入框却无法获取焦点,必须先把键盘收起,再去获取下面输入框焦点,这样用户体验也非常不好,那有什么办法呢? 
系统的adjustResizeadjustPan有什么区别,他们使用时的注意事项,有什么系统要求及蔽端呢?

下面对几种在开发中常用的方法进行总结:

方法一:非透明状态栏下使用adjustResize和adjustPan,或是透明状态栏下使用fitsSystemWindows=true属性

主要实现方法: 
AndroidManifest.xml对应的Activity里添加 
android:windowSoftInputMode=”adjustPan”或是android:windowSoftInputMode=”adjustResize”属性 
这两种属性的区别,官方的解释是: 

这两个属性作用都是为了调整界面使键盘不挡住输入框 ,我这里对这两种属性使用场景、优缺点、注意事项进行了全方面总结,不知大家平时使用时是否注意到了。

属性 注意事项 优缺点 失效情况 适用情况
adjustResize 需要界面本身可调整尺寸,
如在布局添加ScrollView,或输入控件属于RecycleView/ListView某一项
优点:1.不会把标题栏顶出当前布局;
2.有多项输入时,当前输入框下面的输入框可上下滑动输入 
缺点:1.需要界面本身可调整尺寸;
2. 全屏时失效
1.Activity主窗口尺寸无法调整;
2.Activity全屏
3.android5.0以上通过style设置沉浸式状态栏模式而不设置fitSystemWindow为true
非全屏或是非沉浸式状态栏输入界面,输入框比较多
adjustPan 页面不会重新布局,当前输入框和键盘会直接将当前输入框以上界面整体向上平移,这样即使界面包含标题栏,也会被顶上去 优点: 使用简单,不需要界面本身可调整尺寸,不会有失效情况 
缺点: 会把标题栏顶出当前布局;有多项输入时,当前输入框下面的输入框无法输入,必须收起键盘显示输入框再输入
有少量输入项,且输入量居界面上方
fitsSystemWindows 如果多个View设置了fitsSystemWindows=”true”,只有初始的view起作用,都是从第一个设置了fitsSystemWindows的view开始计算padding 优点:使用简单,需要沉浸式状态栏的界面,不需要自己计算padding状态栏的高度
缺点:使用有限制
1.View 的其他 padding 值被重新改写了
2.手机系统版本>=android 4.4
1.界面全屏
2.设置界面主题为沉浸式状态栏
  • adjustResize失效情况:activity设置了全屏属性指Theme.Light.NotittleBar.Fullscreen(键盘弹起时会将标题栏也推上去)或者设置了activity对应的主题中android:windowTranslucentStatus属性,设置方式为:android:windowTranslucentStatus=true,这时如果对应的页面上含有输入框,将会导致点击输入框时软键盘弹出后键盘覆盖输入框,导致输入框看不见。
  • fitsSystemWindows=”true”只有初始的view起作用:如果在布局中不是最外层控件设置fitsSystemWindows=”true”那么设置的那个控件高度会多出一个状态栏高度。若有多个view设置了,因第一个view已经消耗掉insect,其他view设置了也会被系统忽略。

假设原始界面是一个LinearLayout包含若干EditText,如下图所示,在分别使用两种属性时的表现。

1、adjustPan

整个界面向上平移,使输入框露出,它不会改变界面的布局;界面整体可用高度还是屏幕高度,这个可以通过下面的截图看出,如点击输入框6,输入框会被推到键盘上方,但输入框1被顶出去了,如果界面包含标题栏,也会被顶出去。

2、adjustResize

需要界面的高度是可变的,或者说Activity主窗口的尺寸是可以调整的,如果不能调整,则不会起作用。 
例如:Activity的xml布局中只有一个LinearLayout包含若干EditText,在Activity的AndroidMainfest.xml中设置android:windowSoftInputMode=”adjustResize”属性,点击输入框6, 发现软键盘挡住了输入框6,并没有调整,如下图所示:

但使用这两种属性,我们可以总结以下几点:

1) 使用adjustPan, 如果需要输入的项比较多时,点击输入框,当前输入项会被顶到软键盘上方,但若当前输入框下面还有输入项时,却需要先收起键盘,再点击相应的输入项才能输入。这样操作太繁琐了,对于用户体验不大好;

2) adjustResize的使用,需要界面本身可显示的窗口内容能调整,可结合scrollview使用;

方法二:在界面最外层布局包裹ScrollView

1、只使用ScrollView

在相应界面的xml布局中,最外层添加一个ScrollView,不在AndroidMainfest.xml中设置任何android:windowSoftInputMode属性,此时点击输入框,输入框均不会被软键盘档住。即使当前输入框下方也有输入框,在键盘显示的情况下,也可以通过上下滑动界面来输入,而不用先隐藏键盘,点击下方输入框,再显示键盘输入。 
我们可以根据Android Studio的Inspect Layout工具来查看界面真正占用的布局高度,工具在

通过该工具,我们看到: 
界面真正能用的高度=屏幕高度-状态栏高度-软键盘高度 
界面中蓝框是真正界面所用的高度:

2、ScrollView+adjustPan

我们再在该类的AndroidMainfest.xml中设置windowSoftInputMode属性为adjustPan

 <activity android:name=".TestInputActivity"
  android:windowSoftInputMode="adjustPan">

发现当前输入框不会被挡住,但是输入框比较多时,在有键盘显示时,界面上下滑动,但只能滑动部分,且如果输入框在界面靠下方时,点击输入框,标题栏也会被顶出去,如下图所示:

我们借助Inspect Layout工具查看此设置布局可用高度,从下图可以看出,此时布局可用高度是屏幕的高度,上下滑动也只是此屏的高度,在输入框9以下的输入框滑不出来,向上滑动,也只能滑到输入框1。

3、ScrollView+adjustResize

我们前面说过adjustResize的使用必须界面布局高度是可变的,如最外层套个ScrollView或是界面可收缩的,才起作用。这里在该类的AndroidMainfest.xml中设置windowSoftInputMode属性为adjustResize

 <activity android:name=".TestInputActivity"
  android:windowSoftInputMode="adjustResize">

发现效果和1不设置任何windowSoftInputMode属性类似,其使用高度也是:屏幕高度-状态栏高度-软键盘高度

我们再来看看windowSoftInputMode默认属性值stateUnspecified:

可以看出,系统将选择合适的状态,也就是在界面最外层包含一层ScrollView时,设置默认属性值stateUnspecified其实就是adjustResize属性。

但以下两方面无法满足需求:

1) 当Activity设置成全屏fullscreen模式时或是使用沉浸式状态栏时,界面最外层包裹 ScrollView,当输入框超过一屏,当前输入框下面的输入框并不能上下滑动来输入,情况类似于ScrollView+adjustPan,只能滑动部分,通过Inspect Layout也可以看到,界面可用高度是整个屏幕高度,并不会进行调整高度。即使设置adjustResize,也不起作用。 
2) 如果是类似于注册界面或是登录界面,键盘会挡住输入框下面的登录按钮。

沉浸式状态栏/透明状态栏情况下

自android系统4.4(API>=19)就开始支持沉浸式状态栏,当使用觉System windows(系统窗口),显示系统一些属性和操作区域,如 最上方的状态及没有实体按键的最下方的虚拟导航栏。 
android:fitsSystemWindows=“true”会使得屏幕上的可布局空间位于状态栏下方与导航栏上方

方法三:使用scrollTo方法,当键盘弹起时,让界面整体上移;键盘收起,让界面整体下移

使用场景:针对界面全屏或是沉浸式状态栏,输入框不会被键盘遮挡。主要用于一些登录界面,或是需要把界面整体都顶上去的场景。

1、主要实现步骤:

(1) 获取Activity布局xml的最外层控件,如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:id="@+id/main"
 tools:context="com.example.liubin1.softkeyboardhelper.MainActivity">
 <EditText
 android:id="@+id/name"
 android:hint="请输入用户名:"
 android:layout_centerInParent="true"
 android:layout_width="match_parent"
 android:layout_height="50dp"
 />
 <EditText
 android:id="@+id/pas"
 android:layout_below="@id/name"
 android:hint="请输入密码:"
 android:layout_centerInParent="true"
 android:layout_width="match_parent"
 android:layout_height="50dp"
 />
 <Button
 android:id="@+id/login_btn"
 android:layout_below="@id/rpas"
 android:layout_centerHorizontal="true"
 android:text="登录"
 android:layout_width="180dp"
 android:layout_height="50dp" />
</RelativeLayout>

先获取到最外层控件

RelativeLayout main = (RelativeLayout) findViewById(R.id.main);

(2) 获取到最后一个控件,如上面的xml文件,最后一个控件是Button

Button login_btn = (Button) findViewById(R.id.login_btn);

(3) 给最外层控件和最后一个控件添加监听事件

//在Activity的onCreate里添加如下方法addLayoutListener(main,login_btn);/**
 * addLayoutListener方法如下
 * @param main 根布局
 * @param scroll 需要显示的最下方View
 */
 public void addLayoutListener(final View main, final View scroll) {
 main.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {  @Override
  public void onGlobalLayout() {
  Rect rect = new Rect();  //1、获取main在窗体的可视区域
  main.getWindowVisibleDisplayFrame(rect);  //2、获取main在窗体的不可视区域高度,在键盘没有弹起时,main.getRootView().getHeight()调节度应该和rect.bottom高度一样
  int mainInvisibleHeight = main.getRootView().getHeight() - rect.bottom;  int screenHeight = main.getRootView().getHeight();//屏幕高度
  //3、不可见区域大于屏幕本身高度的1/4:说明键盘弹起了
  if (mainInvisibleHeight > screenHeight / 4) {   int[] location = new int[2];
   scroll.getLocationInWindow(location);   // 4、获取Scroll的窗体坐标,算出main需要滚动的高度
   int srollHeight = (location[1] + scroll.getHeight()) - rect.bottom;   //5、让界面整体上移键盘的高度
   main.scrollTo(0, srollHeight);
  } else {  //3、不可见区域小于屏幕高度1/4时,说明键盘隐藏了,把界面下移,移回到原有高度
   main.scrollTo(0, 0);
  }
  }
 });
 }
}

2、实现原理:

此方法通过监听Activity最外层布局控件来检测软键盘是否弹出,然后去手动调用控件的scrollTo方法达到调整布局目的。

3、弊端:

此种方法需要在当前界面写比较多的代码,在某些手机上,若输入时,软键盘高度是可变的,如中英文切换,高度变化时,会发现适配的不大好。如下图:

从上图可以看出,如果键盘高度变化,键盘还是会挡住登录按钮。

方法四:适配键盘高度变化情况,当键盘弹起时,让界面整体上移;键盘收起,让界面整体下移

此方法主要是通过在需要移动的控件外套一层scrollView,同时最布局最外层使用自定义view监听键盘弹出状态,计算键盘高度,再进行计算需要移动的位置,这个和方法三有点类似,但能适配键盘高度变化情况。

实现步骤

(1) 先写自定义View,实时临听界面键盘弹起状态,计算键盘高度

public class KeyboardLayout extends FrameLayout {
 private KeyboardLayoutListener mListener; private boolean mIsKeyboardActive = false; //输入法是否激活
 private int mKeyboardHeight = 0; // 输入法高度
 public KeyboardLayout(Context context) { this(context, null, 0);
 } public KeyboardLayout(Context context, AttributeSet attrs) { this(context, attrs, 0);
 } public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 监听布局变化
 getViewTreeObserver().addOnGlobalLayoutListener(new KeyboardOnGlobalChangeListener());
 } public void setKeyboardListener(KeyboardLayoutListener listener) {
 mListener = listener;
 } public KeyboardLayoutListener getKeyboardListener() { return mListener;
 } public boolean isKeyboardActive() { return mIsKeyboardActive;
 } /**
 * 获取输入法高度
 *
 * @return
 */
 public int getKeyboardHeight() { return mKeyboardHeight;
 } public interface KeyboardLayoutListener {
 /**
  * @param isActive 输入法是否激活
  * @param keyboardHeight 输入法面板高度
  */
 void onKeyboardStateChanged(boolean isActive, int keyboardHeight);
 } private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {
 int mScreenHeight = 0; private int getScreenHeight() {  if (mScreenHeight > 0) {  return mScreenHeight;
  }
  mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
   .getDefaultDisplay().getHeight();  return mScreenHeight;
 } @Override
 public void onGlobalLayout() {
  Rect rect = new Rect();  // 获取当前页面窗口的显示范围
  ((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);  int screenHeight = getScreenHeight();  int keyboardHeight = screenHeight - rect.bottom; // 输入法的高度
  boolean isActive = false;  if (Math.abs(keyboardHeight) > screenHeight / 4) {
  isActive = true; // 超过屏幕五分之一则表示弹出了输入法
  mKeyboardHeight = keyboardHeight;
  }
  mIsKeyboardActive = isActive;  if (mListener != null) {
  mListener.onKeyboardStateChanged(isActive, keyboardHeight);
  }
 }
 }
}

(2) xml文件编写,在界面最外层套上自定义view,在需要滚动的控件外层添加scrollView

public class KeyboardLayout extends FrameLayout {
 private KeyboardLayoutListener mListener; private boolean mIsKeyboardActive = false; //输入法是否激活
 private int mKeyboardHeight = 0; // 输入法高度
 public KeyboardLayout(Context context) { this(context, null, 0);
 } public KeyboardLayout(Context context, AttributeSet attrs) { this(context, attrs, 0);
 } public KeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 监听布局变化
 getViewTreeObserver().addOnGlobalLayoutListener(new KeyboardOnGlobalChangeListener());
 } public void setKeyboardListener(KeyboardLayoutListener listener) {
 mListener = listener;
 } public KeyboardLayoutListener getKeyboardListener() { return mListener;
 } public boolean isKeyboardActive() { return mIsKeyboardActive;
 } /**
 * 获取输入法高度
 *
 * @return
 */
 public int getKeyboardHeight() { return mKeyboardHeight;
 } public interface KeyboardLayoutListener {
 /**
  * @param isActive 输入法是否激活
  * @param keyboardHeight 输入法面板高度
  */
 void onKeyboardStateChanged(boolean isActive, int keyboardHeight);
 } private class KeyboardOnGlobalChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {
 int mScreenHeight = 0; private int getScreenHeight() {  if (mScreenHeight > 0) {  return mScreenHeight;
  }
  mScreenHeight = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
   .getDefaultDisplay().getHeight();  return mScreenHeight;
 } @Override
 public void onGlobalLayout() {
  Rect rect = new Rect();  // 获取当前页面窗口的显示范围
  ((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);  int screenHeight = getScreenHeight();  int keyboardHeight = screenHeight - rect.bottom; // 输入法的高度
  boolean isActive = false;  if (Math.abs(keyboardHeight) > screenHeight / 4) {
  isActive = true; // 超过屏幕五分之一则表示弹出了输入法
  mKeyboardHeight = keyboardHeight;
  }
  mIsKeyboardActive = isActive;  if (mListener != null) {
  mListener.onKeyboardStateChanged(isActive, keyboardHeight);
  }
 }
 }
}

(3) Activity调用,自定义view控件添加键盘响应,在键盘变化时调用scrollViewsmoothScrollTo去滚动界面

 /**
 * 监听键盘状态,布局有变化时,靠scrollView去滚动界面
 */
 public void addLayoutListener() {
 bindingView.mainLl.setKeyboardListener(new KeyboardLayout.KeyboardLayoutListener() {  @Override
  public void onKeyboardStateChanged(boolean isActive, int keyboardHeight) {
  Log.e("onKeyboardStateChanged", "isActive:" + isActive + " keyboardHeight:" + keyboardHeight);  if (isActive) {
   scrollToBottom();
  }
  }
 });
 } /**
 * 弹出软键盘时将SVContainer滑到底
 */
 private void scrollToBottom() {
 bindingView.loginLl.postDelayed(new Runnable() {  @Override
  public void run() {
  bindingView.loginLl.smoothScrollTo(0, bindingView.loginLl.getBottom() + SoftKeyInputHidWidget.getStatusBarHeight(LoginActivityForDiffkeyboardHeight.this));
  }
 }, 100);
 }

实现效果如下:

可以看到键盘高度变化了,也不会影响界面布局

方法五:监听Activity顶层View,判断软键盘是否弹起,对界面重新绘制

此方法的实现来自android中提出的issue 5497 https://code.google.com/p/android/issues/detail?id=5497

使用场景:针对界面全屏或是沉浸式状态栏,界面包含比较多输入框,界面即使包裹了一层ScrollView,在键盘显示时,当前输入框下面的输入不能通过上下滑动界面来输入。

感谢下面提出评论的同学,指出此方法的不适配问题,之前写的博文在华为小米手机上确实有不适配情况,在输入时,键盘有时会错乱,现在已加入适配。

一、实现步骤:

1、把SoftHideKeyBoardUtil类复制到项目中; 
2、在需要使用的ActivityonCreate方法中添加:SoftHideKeyBoardUtil.assistActivity(this);即可。

二、实现原理:

SoftHideKeyBoardUtil类具体代码如下:

/**
 * 解决键盘档住输入框
 * Created by SmileXie on 2017/4/3.
 */public class SoftHideKeyBoardUtil {
 public static void assistActivity (Activity activity) { new SoftHideKeyBoardUtil(activity);
 } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; //为适应华为小米等手机键盘上方出现黑条或不适配
 private int contentHeight;//获取setContentView本来view的高度
 private boolean isfirst = true;//只用获取一次
 private int statusBarHeight;//状态栏高度
 private SoftHideKeyBoardUtil(Activity activity) { //1、找到Activity的最外层布局控件,它其实是一个DecorView,它所用的控件就是FrameLayout
 FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); //2、获取到setContentView放进去的View
 mChildOfContent = content.getChildAt(0); //3、给Activity的xml布局设置View树监听,当布局有变化,如键盘弹出或收起时,都会回调此监听
  mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { //4、软键盘弹起会使GlobalLayout发生变化
  public void onGlobalLayout() {  if (isfirst) {
   contentHeight = mChildOfContent.getHeight();//兼容华为等机型
   isfirst = false;
  }  //5、当前布局发生变化时,对Activity的xml布局进行重绘
  possiblyResizeChildOfContent();
  }
 }); //6、获取到Activity的xml布局的放置参数
 frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
 } // 获取界面可用高度,如果软键盘弹起后,Activity的xml布局可用高度需要减去键盘高度
 private void possiblyResizeChildOfContent() { //1、获取当前界面可用高度,键盘弹起后,当前界面可用布局会减少键盘的高度
 int usableHeightNow = computeUsableHeight(); //2、如果当前可用高度和原始值不一样
 if (usableHeightNow != usableHeightPrevious) {  //3、获取Activity中xml中布局在当前界面显示的高度
  int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();  //4、Activity中xml布局的高度-当前可用高度
  int heightDifference = usableHeightSansKeyboard - usableHeightNow;  //5、高度差大于屏幕1/4时,说明键盘弹出
  if (heightDifference > (usableHeightSansKeyboard/4)) {  // 6、键盘弹出了,Activity的xml布局高度应当减去键盘高度
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
   frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
  } else {
   frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
  }
  } else {
  frameLayoutParams.height = contentHeight;
  }  //7、 重绘Activity的xml布局
  mChildOfContent.requestLayout();
  usableHeightPrevious = usableHeightNow;
 }
 } private int computeUsableHeight() {
 Rect r = new Rect();
 mChildOfContent.getWindowVisibleDisplayFrame(r); // 全屏模式下:直接返回r.bottom,r.top其实是状态栏的高度
 return (r.bottom - r.top);
 }
}

它的实现原理主要是: 
(1) 找到Activity的最外层布局控件,我们知道所有的Activity都是DecorView,它就是一个FrameLayout控件,该控件id是系统写死叫R.id.content,就是我们setContentView时,把相应的View放在此FrameLayout控件里

FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);

所以content.getChildAt(0)获取到的mChildOfContent,也就是我们用setContentView放进去的View。 
(2) 给我们的Activity的xml布局View设置一个Listener监听

mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener({
 possiblyResizeChildOfContent();
});

View.getViewTreeObserver()可以获取一个ViewTreeObserver对象——它是一个观察者,用以监听当前View树所发生的变化。这里所注册的addOnGlobalLayoutListener,就是会在当前的View树的全局布局(GlobalLayout)发生变化、或者其中的View可视状态有变化时,进行通知回调。『软键盘弹出/隐 』都能监听到。

(3) 获取当前界面可用高度

private int computeUsableHeight() {
 Rect rect = new Rect();
 mChildOfContent.getWindowVisibleDisplayFrame(rect); // rect.top其实是状态栏的高度,如果是全屏主题,直接 return rect.bottom就可以了
 return (rect.bottom - rect.top);
}

如下图所示:

(4) 重设高度, 我们计算出的可用高度,是目前在视觉效果上能看到的界面高度。但当前界面的实际高度是比可用高度要多出一个软键盘的距离的。

注意:如果既使用了沉浸式状态栏,又加了fitSystetemWindow=true属性,就需要在AndroidMainfest.xml注册Activity的地方添加上以下属性。因为你两种都用,系统不知道用哪种了。fitSystetemWindow已经有resize屏幕的作用。

android:windowSoftInputMode="stateHidden|adjustPan"

通过上面的这种方法,一般布局输入键盘挡住输入框的问题基本都能解决。即使界面全屏或是沉浸式状态栏情况。

总结:

下面对上面几种方法进行对比:

  • 方法一:优点:使用简单,只需在Activity的AndroidMainfest.xml中设置windowSoftInput属性即可。 
    注意点:adjustResize属性必须要界面大小可以自身改变; 
    缺点:当输入框比较多时,当前输入框下方的输入框会初键盘挡住,须收起键盘再进入输入;使用adjustPan,输入框较多时,因它是把界面当成一个整体,只会显示一屏的高度,会把ActionBar顶上去。
  • 方法二:优点:使用简单,只需在Activity的最外层布局包裹一个ScrollView即可。 
    注意点:不可使用adjustPan属性,否则ScrollView失效; 
    缺点:对于全屏时,在键盘显示时,无法上下滑动界面达到输入的目的;
  • 方法三:优点:可以解决全屏时,键盘挡入按钮问题。 
    缺点:只要有此需求的Activity均需要获取到最外层控件和最后一个控件,监测键盘是否弹出,再调用控件的scrollTo方法对界面整体上移或是下移。代码冗余。对于键盘高度变化时,适配不好。
  • 方法四:优点:可以解决全屏时,键盘挡入按钮问题。 
    缺点:只要有此需求的Activity均需要获取到最外层控件和最后一个控件,布局多出一层。
  • 方法五:优点:可以解决全屏时,键盘挡入输入框问题。只需要写一个全局类,其他有需求的界面直接在onCreate方法里调用此类的全局方法,即可。 
    缺点:多用了一个类。

综上所述: 
1) 当输入框比较少时,界面只有一个输入框时,可以通过方法一设置adjustPan; 
2) 如果对于非全屏/非沉浸式状态栏需求,只需要使用方法二ScrollView+adjustResize; 
3) 如果对于使用沉浸式状态栏,使用fitSystemWindow=true属性,按道理android系统已经做好适配,键盘不会挡住输入框; 
4) 如果全屏/沉浸式状态栏界面,类似于登录界面,有需要把登录键钮或是评论按钮也顶起,如果键盘没有变化需求,可以使用方法三,若需要适配键盘高度变化,则需要使用方法四; 
5) 如果界面使用全屏或沉浸式状态栏,没有使用fitSystemWindow=true属性,一般如需要用到抽屈而且状态栏颜色也需要跟着变化,则选择方法五更恰当。

您可能感兴趣的文章:

  • Android仿支付宝自定义密码输入框及安全键盘(密码键盘)
  • Android自定义密码输入框和数字键盘
  • Android软键盘挡住输入框的终极解决方案
  • Android仿支付宝、京东的密码键盘和输入框
(0)

相关推荐

  • Android仿支付宝自定义密码输入框及安全键盘(密码键盘)

     0.前言 之前做过的项目里有运用到一个支付场景:用户办理业务时需要输入交易密码,并且可根据平台下发的支付方式进行选择.这与支付宝的密码输入方式十分相似,如果使用Android系统或者第三方软件的键盘,会有密码泄露的风险.因此,大多数的应用软件使用的是自定义的密码输入框及安全键盘. 由于密码输入方式需要实现一个从底部弹出的效果,因此总体上决定采用BottomSheetDialog来进行封装,同时为了提高安全性,还应该随机生成键盘上的数字,界面如下图所示:   首先新建一个PasswordInpu

  • Android仿支付宝、京东的密码键盘和输入框

    首先看下效果图 一:布局代码 键盘由0~9的数字,删除键和完成键组成,也可以根据需求通过GridView适配器的getItemViewType方法来定义.点击键的时候背景有变色的效果. 密码输入框由六个EditText组成,每个输入框最对能输入一个数字,监听最后一个输入框来完成密码输入结束的监听. 二:键盘 键盘中的主要逻辑处理,键盘样式,item的点击事件 @Override public int getViewTypeCount() { return 2; } @Override publi

  • Android软键盘挡住输入框的终极解决方案

    前言 开发做得久了,总免不了会遇到各种坑. 而在Android开发的路上,『软键盘挡住了输入框』这个坑,可谓是一个旷日持久的巨坑--来来来,我们慢慢看. 入门篇 最基本的情况,如图所示:在页面底部有一个EditText,如果不做任何处理,那么在软键盘弹出的时候,就有可能会挡住EditText. 对于这种情况的处理其实很简单,只需要在AndroidManifest文件中对activity设置:android:windowSoftInputMode的值adjustPan或者adjustResize即

  • Android自定义密码输入框和数字键盘

    实现了一个自定义的密码输入框和自定义数字键盘,用作用户支付密码设置界面.先上效果图如下,方格样式,以及点击空白处隐藏软键盘. 控件实现清单: 1)集成于EditText的输入框控件:PasswordInputView.java 2)数字键盘工具类:NumKeyboardUtil.java 3)xml文件:number.xml 4)attrs样式 5)layout文件 具体内容: PasswordInputView.java public class PasswordInputView exten

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

    在开发中,经常会遇到键盘挡住输入框的情况,比如登录界面或注册界面,弹出的软键盘把登录或注册按钮挡住了,用户必须把软键盘收起,才能点击相应按钮,这样的用户体验非常不好.像微信则直接把登录按钮做在输入框的上面,但有很多情况下,这经常满足不了需求.同时如果输入框特别多的情况下,点击输入时,当前输入框没被挡住,但是当前输入框下面的输入框却无法获取焦点,必须先把键盘收起,再去获取下面输入框焦点,这样用户体验也非常不好,那有什么办法呢?  系统的adjustResize和adjustPan有什么区别,他们使

  • Android WebView软键盘遮挡输入框方案详解

    目录 背景 纪实 方案 实现 总结 背景 笔者在使用 WebView 加载含有输入框的 H5 页面时,点击输入框后,输入框会被软键盘遮挡住,无法看到输入的内容,这很影响用户体验. 笔者想着这种业务场景比较常见,遂上网搜索一番,果不其然,有不少同志遇到这个问题,想来这个问题很好解决了.笔者一一尝试了同志们提供的解决方案,结果要不是没有作用,要不是效果不太满意,只好自己另辟蹊径了. 注:在笔者的业务场景中,App是全屏的,即没有顶部的系统栏,也没有底部的导航栏,所以笔者的解决方案,可能不适用于其他场

  • 解决Android软键盘弹出覆盖h5页面输入框问题

    之前我们在使用vue进行 h5 表单录入的过程中,遇到了Android软键盘弹出,覆盖 h5页面 输入框 问题,在此进行回顾并分享给大家: 系统:Android 条件:当输入框在可视区底部或者偏下的位置 触发条件:输入框获取焦点,弹出软键盘 表现:软键盘 覆盖 h5页面中的输入框 问题分析: 1.发现问题:当前页面中box为flex布局,内容为上下固定高,中间自适应(中间区域内容过多会出现滚动条,input框在wrapper的底部),input获取焦点,手机键盘弹出,input未上移到可视区内,

  • Android 监听软键盘状态的实例详解

    Android 监听软键盘状态的实例详解 近日遇到要检测软键盘是否显示或隐藏的问题,搜了一下网上,最后找到一个很简单的,记录一下. activityRoot是activity的根view,就是xml里面的第一个view,给它设置一个id. final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(ne

  • Android 软引用和弱引用详解及实例代码

    Android 软引用 和 弱引用    1.  SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象:需要获取对象时,可以调用get方法. 2.  WeakReference<T>:弱引用-->随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收.要获取对象时,同样可以调用get方法. 3. WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收,SoftReference多用作来实现缓存机制(cache

  • Android软键盘遮挡的四种完美解决方案

    一.问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时输入框被系统键盘遮挡了,大大降低了用户操作体验,这就是开发中非常常见的软键盘遮挡的问题,该如何解决? 二.简单解决方案 方法一 在你的activity中的oncreate中setContentView之前写上这个代码 getWindow().setSoftInputMode(WindowManage

  • Android 软键盘出现不适应的解决办法总结

    Android 软键盘出现不适应的解决办法总结 前言: 很多写登录界面的开发者都会遇到一个问题:那就是在登录界面时,当你点击输入框时,下边的按钮有时会被输入框挡住,这个不利于用户的体验,所以很多人希望软键盘弹出时,也能把按钮挤上去.很多开发者想要监听键盘的状态,这无疑是一个很麻烦的做法. 我们可以在AndroidManifest.xml的Activity设置属性:Android:windowSoftInputMode = "adjustResize" ,软键盘弹出时,要对主窗口布局重新

  • Android 软键盘弹出隐藏挤压界面等各种问题小结

    Android中软键盘的使用是非常多的,下面为软键盘常用的设置: 1.横屏时,点击输入框出现全键盘解决方案: 在EditText.searchview等控件中加 android:imeOptions="flagNoExtractUi" 2.竖屏时,安卓会出现半屏. case1:你的输入框处于中下的位置,这样的话,键盘可能挡住输入框. 解决方法:在manifest中对activity设置 android:windowSoftInputMode="adjustResize&quo

  • Android软键盘显示模式及打开和关闭方式(推荐)

    Android软键盘显示模式: Android定义了一个属性,名字为windowSoftInputMode, 用它可以让程序可以控制活动主窗口调整的方式.我们可以在AndroidManifet.xml中对Activity进行设置.如:android:windowSoftInputMode="stateUnchanged|adjustPan" 该属性可选的值有两部分,一部分为软键盘的状态控制,另一部分是活动主窗口的调整.前一部分本文不做讨论,请读者自行查阅android文档.     模

随机推荐