一.windowSoftInputMode属性
1.概念
(此小节抄录来自)
android定义了一个属性,名字为windowSoftInputMode, 这个属性用于设置Activity主窗口与软键盘的交互模式,用于避免软键盘遮挡内容的问题。我们可以在AndroidManifet.xml中对Activity进行设置。如:android:windowSoftInputMode=”stateUnchanged|adjustPan”。
该属性可选的值有两部分,一部分为软键盘的状态控制,控制软键盘是隐藏还是显示,另一部分是Activity窗口的调整,以便腾出空间展示软键盘。
android:windowSoftInputMode的属性设置必须是下面中的一个值,或一个”state”值加一个”adjust”值的组合,各个值之间用 | 分开。
- stateUnspecified-未指定状态:当我们没有设置android:windowSoftInputMode属性的时候,软件默认采用的就是这种交互方式,系统会根据界面采取相应的软键盘的显示模式。
- stateUnchanged-不改变状态:当前界面的软键盘状态,取决于上一个界面的软键盘状态,无论是隐藏还是显示。
- stateHidden-隐藏状态:当设置该状态时,软键盘总是被隐藏,不管是否有输入的需求。
- stateAlwaysHidden-总是隐藏状态:当设置该状态时,软键盘总是被隐藏,和stateHidden不同的是,当我们跳转到下个界面,如果下个页面的软键盘是显示的,而我们再次回来的时候,软键盘就会隐藏起来。
- stateVisible-可见状态:当设置为这个状态时,软键盘总是可见的,即使在界面上没有输入框的情况下也可以强制弹出来出来。
- stateAlwaysVisible-总是显示状态:当设置为这个状态时,软键盘总是可见的,和stateVisible不同的是,当我们跳转到下个界面,如果下个页面软键盘是隐藏的,而我们再次回来的时候,软键盘就会显示出来。
- adjustUnspecified-未指定模式:设置软键盘与软件的显示内容之间的显示关系。当你跟我们没有设置这个值的时候,这个选项也是默认的设置模式。在这中情况下,系统会根据界面选择不同的模式。
- adjustResize-调整模式:改变布局,就是说直接让界面的高度少了一个软键盘的高度,屏幕底部显示软键盘,而界面按照新的高度来重新布局。
- adjustPan-默认模式:直接将界面整体往上移。
- adjustNothing:啥都不做,不会改变布局,也不会改变应用显示的屏幕范围,EditText自然也会被遮挡。
2.使用
windowSoftInputMode默认的时候是”stateUnspecified|adjustUnspecified”,当界面可以滚动的时候,弹出软键盘的时候也可以滑动界面,为确保软键盘空间会移动布局
例子如下:
滚动布局
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
......这里是很多个EditText
</LinearLayout>
</ScrollView>
然后我还发现一个奇怪的迹象,如果我把最外层的ScrollView去掉,界面不会默认弹出软键盘
无滚动布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
......这里都是很多个EditText
</LinearLayout>
windowSoftInputMode属性换成"stateUnspecified|adjustPan",即便界面可以滚动,在弹出软键盘后不能滚动界面,
然后就是以上两种布局不会默认弹出软键盘
windowSoftInputMode属性换成"stateUnspecified|adjustResize",即便界面可以滚动,在弹出软键盘后可以滚动界面,
然后就是以上两种布局默认弹出软键盘
其他state属性和adjust属性之间的配合效果,我就不说了,大家可以试一试
二.软键盘的弹出和隐藏
切换软键盘,也就是如果软键盘是弹出,执行这个代码就会隐藏,反之就会使之弹出
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
强制弹出
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(et,InputMethodManager.SHOW_FORCED)
强制隐藏
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(et.getWindowToken(), 0); //强制隐藏键盘
隐藏系统默认的输入法
(getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
监听软键盘的弹出和隐藏
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
public class SoftKeyBoardListener {
private View rootView;
int rootViewVisibleHeight;
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
public SoftKeyBoardListener(Activity activity) {
rootView = activity.getWindow().getDecorView();
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
if (rootViewVisibleHeight == visibleHeight) {
return;
}
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
public interface OnSoftKeyBoardChangeListener {
void keyBoardShow(int height);
void keyBoardHide(int height);
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
}
三.选定软键盘为哪个EditText弹出
这个是默认为第一个EditText弹出软键盘
Timer timer=new Timer();
timer.schedule(new TimerTask() {
public void run() {
InputMethodManager inputMethodManager=(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
}, 1000); // 秒后自动弹出
第二种就可以指定哪个EditText弹出软键盘
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.requestFocus();
MainActivity.this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
四.不自动弹出软键盘
先前也说通过通过设置android:windowSoftInputMode="stateUnspecified|adjustPan" 可以设置不自动弹出软键盘,还有一种state属性也可以stateHidden
这些都是在AndroidManifest设置的,还有可以在java代码里可以做到,其实也是设置Window的属性,原理一样
getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
五.不影响布局
java代码
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
注册文件
android:windowSoftInputMode="adjustPan"