在android开发的不可避免会遇到EditText和软键盘的问题
本篇博客就是分解各种用法
软键盘遮挡EditText
activity有这么一个属性 android:windowSoftInputMode,我们先看看各个值的含义
- 【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置
- 【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
- 【C】stateHidden:用户选择activity时,软键盘总是被隐藏
- 【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的
- 【E】stateVisible:软键盘通常是可见的
- 【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态
- 【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示
- 【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间
- 【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
那么不让软键盘挡住EditText的方法
在manifest中配置
<activity android:windowSoftInputMode="stateVisible|adjustResize". . . />
软键盘将整个Activity顶出
不让软件盘挡住EditText后,如果我们将windowsSoftInputMode设置为adjustResize 或者 adjustPan 都会导致布局变形或移动,那么软键盘怎么才能只将EditText顶上去,对其它的布局没有影响呢
软键盘只将EditText顶上去
如下这个效果
思路:
1、EditText的位置在布局的最下层
2、获取软键盘的高度
3、软键盘弹出后,设置EditText的 marginBottom 为软件盘的高度
布局 manifest
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/all_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android_custom="http://schemas.android.com/apk/res-auto"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--......-->
</FrameLayout>
<EditText
android:id="@+id/etxt_word"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:cursorVisible="true"
android:minHeight="50dp"
android:gravity="center"
android:visibility="invisible"/>
</RelativeLayout>
<activity
android:name=".activity.MainActivity"
android:windowSoftInputMode="adjustResize"/>
弹出软键盘
/**
* 弹出软键盘
*/
public static boolean showSoftInput(Context context, EditText editText) {
try {
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.requestFocus();
InputMethodManager inputManager = (InputMethodManager) context
.getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
获取软键盘高度,并设置EditText的位置
etxt_word.setVisibility(View.VISIBLE);
showSoftInput(CreateEditActivity.this, etxt_word);
etxt_word.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
/**
* 获取软键盘高度 设置edit text的位置
*/
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//判断有没有必要执行下去
final RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) etxt_word.getLayoutParams();
if (layoutParams.bottomMargin > 0) {
return;
}
//判断窗口可见区域大小
Rect r = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
//如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/4,则表示软键盘显示中,否则软键盘为隐藏状态。
final int heightDifference = mScreenHeight - (r.bottom - r.top);
boolean isKeyboardShowing = heightDifference > mScreenHeight / 4 && heightDifference != mScreenHeight;
if (isKeyboardShowing) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.setMargins(0, 0, 0, heightDifference);
etxt_word.setLayoutParams(layoutParams);
}
}, 200);
}
}
};
OnGlobalLayoutListener 是ViewTreeObserver的内部类,当一个视图树的布局发生改变时,可以被ViewTreeObserver监听到,这是一个注册监听视图树的观察者(observer),在视图树的全局事件改变时得到通知。ViewTreeObserver不能直接实例化,而是通过getViewTreeObserver()获得。