导读:
日常开发中我们经常会用到EditText输入框,但有时我们的输入框会出现被软键盘界面阻挡,那么我们就会想到设置android:windowSoftInputMode属性
但是,当我们用的正爽的时候,又会出现什么布局上移,ba..ba..ba的bug
因此,本篇将针对个人在开发中遇到的”软键盘阻挡输入框”问题介绍
android:windowSoftInputMode属性说明
属性 | 说明 |
---|---|
stateUnspecified | 软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置 |
stateUnchanged | 当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示 |
stateHidden | 用户选择activity时,软键盘总是被隐藏 |
stateAlwaysHidden | 当该Activity主窗口获取焦点时,软键盘也总是被隐藏的 |
stateVisible | 软键盘通常是可见的 |
stateAlwaysVisible | 用户选择activity时,软键盘总是显示的状态 |
adjustUnspecified | 默认设置,通常由系统自行决定是隐藏还是显示 |
adjustResize | 该Activity总是调整屏幕的大小以便留出软键盘的空间 |
adjustPan | 当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分 |
adjustNothing | 不调整窗口大小或平移窗口,软键盘就默认显示,会覆盖后面内容 |
这个属性能影响两个事情:
- 当有焦点产生时,软键盘是隐藏还是显示
- 是否减少活动主窗口大小以便腾出空间放软键盘
它的设置必须是下面的一个值,或者”state…| adjust..”
正常情况来说,如果要防止软键盘挡住输入框如上表设置属性就能解决…
代码实现:
//adjustPan
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
//adjustResize
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
清单文件对应节点实现:
<!-- 静态设置输入模式 -->
<!-- android:windowSoftInputMode="adjustResize" -->
<activity
android:name=".activity.AdjustResize_KeyboardActivity"
android:windowSoftInputMode="adjustResize"/>
<!-- android:windowSoftInputMode="adjustPan" -->
<activity
android:name=".activity.AdjustPan_KeyboardActivity"
android:windowSoftInputMode="adjustPan"/>
部分属性应用场景说明:
- 使用adjustPan,如果有几个EditText,当点击第一个EditText时,下方的EditText会被软键盘界面覆盖
- 使用adjustPan,如果输入框在软键盘后面,软键盘会把输入框以上的布局(包括ToolBar)挤出屏幕外
- 使用adjustResize,当使用LinearLayout作为输入框的父布局时,软键盘会覆盖输入框
- 使用adjustResize,当控件设置了background属性,或设置了权重的imageView会发生变形,该使用adjustPan
开发中遇到的Bug,以及解决方案:
设置了沉浸式/透明状态栏后,adjustResize失效问题
在根布局或者父布局设置android:fitsSystemWindows=”true”即可解决
“全屏模式”使用adjustResize无效,而且会类似adjustPan把上方布局挤出屏幕外
官方认为”全屏模式”指的是App自己接管了状态栏的控制,如使用了Fullscreen主题、使用了『状态色着色』、『沉浸式状态栏』、『Immersive Mode』等等
个人开发也有一段时间,由于很少遇到需要全屏(状态栏也隐藏)的应用,
真说有的话,那就是游戏里的,不过一旦设置Fullscreen主题一类的全屏,点击EditText输入框会跳转到一个全屏模式的输入界面,
因此这里就不作处理了,有兴趣的同学可以根据以下代码深入研究下,这里就不赘述了.
使用:(最终效果类似adjustResize)
1.把AndroidBug5497Workaround类复制到项目中
2.在需要填坑的activity的onCreate方法中添加一句AndroidBug5497Workaround.assistActivity(this)即可。
----------------------------------------------------
/*
* @本类描述 网上收集的,解决"全屏模式"下,adjustResize失效方案
*
* @内容说明 解决:
* 1.非全屏模式下使用adjustPan无效问题
* 2.全屏模式下使用adjustPan和adjustResize无效问题
*
* @补充内容 有兴趣的同学可以学下里面的思路,自己写一个解决方案(*^__^*) 嘻嘻……)
*
* ---------------------------------
* @更新时间
* @新增内容
*
*/
public class AndroidBug5497Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity(Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private AndroidBug5497Workaround(Activity activity) {
//拿到当前XML文件的根布局
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
//监听当前View的状态,进行通知回调,即"软键盘弹出""
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
/**
* 重新设置高度
* <p>
* 把界面高度设置为可用高度
*/
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
// int usableHeightSansKeyboard = activity.getWindowManager().getDefaultDisplay().getHeight();//获取屏幕尺寸,不包括虚拟功能高度 用这个可以完美解决
//findViewById(android.R.id.content).getMeasuredHeight() 也可以解决虚拟按键问题
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
//排除其他View引起的变化,专注软键盘变化