android:windowSoftInputMode属性一共同拥有9个取值。各自是:
stateUnspecified:
当设置属性为stateUnspecified的时候,系统是默认不弹出软键盘的。可是当有获得焦点的输入框的界面有滚动的需求的时候,会自己主动弹出软键盘。至于为什么非要强调要获取焦点的输入框。这是由于,假设不是输入框获取焦点。软键盘也是不会自己主动弹出的。让界面不自己主动弹出软键盘的当中一个解决方式,就是在xml文件里。设置一个非输入框控件获取焦点,从而阻止键盘弹出。
stateUnchanged:
当前界面的软键盘状态,取决于上一个界面的软键盘状态。举个样例,假如当前界面键盘是隐藏的,那么跳转之后的界面,软键盘也是隐藏的;假设当前界面是显示的,那么跳转之后的界面,软键盘也是显示状态。
stateHidden:
设置了这个属性,那么键盘状态一定是隐藏的,无论上个界面什么状态。也无论当前界面有没有输入的需求,反正就是不显示。因此,我们能够设置这个属性,来控制软键盘不自己主动的弹出。
stateAlwaysHidden:
stateAlwaysHidden不管怎样都是隐藏的,可是假设在跳转到下个界面的时候。软键盘被召唤出来了。那么当下个界面被用户返回的时候,键盘应该是不会被隐藏的,可是,我还没有找到可以跳转到下个界面,还让当前界面软键盘不消失的方法。所以临时不能验证
stateVisible:
设置为这个属性,能够将软键盘召唤出来,即使在界面上没有输入框的情况下也能够强制召唤出来。
stateAlwaysVisible:
当我们设置为stateVisible属性,假设当前的界面键盘是显示的,当我们点击button跳转到下个界面的时候,软键盘会由于输入框失去焦点而隐藏起来,当我们再次回到当前界面的时候,键盘这个时候是隐藏的。可是假设我们设置为stateAlwaysVisible,我们跳转到下个界面,软键盘还是隐藏的,可是当我们再次回来的时候。软键盘是会显示出来的
adjustUnspecified:
这个选项也是默认的设置模式。在这中情况下,系统会依据界面选择不同的模式。假设界面里面有能够滚动的控件,比方ScrowView。系统会减小能够滚动的界面的大小,从而保证即使软键盘显示出来了,也能够看到全部的内容。假设布局里面没有滚动的控件。那么软键盘可能就会盖住一些内容,我们从以下的图中能够看出区别。
adjustResize:
这个属性表示Activity的主窗体总是会被调整大小,从而保证软键盘显示空间.对于没有滑动控件的布局,布局的位置并不会发生变化.软键盘会遮住输入框. 如果Activity 的窗体有滑动控件, 就会压缩该可滑动的控件. 如键盘不会遮住输入法.
adjustPan:
设置这个属性,Activity的窗口大小并不会调整来保证软键盘的空间, 而是直接将整个布局往上顶.不会压缩可滑动控件.
常用模式:
1.登陆界面有用户名, 密码,底部有登陆按钮, 要求弹出软键盘时显示"登陆"按钮
a. 布局文件:
<activity android:name=".ui.activity.login.LoginActivity"
/> //android:windowSoftInputMode: 不可用adjustReSize
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/main"
android:layout_height="match_parent"
android:background="@color/white"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".ui.activity.LoginActivity">
<com.hjq.bar.TitleBar
android:id="@+id/tb_login_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/space_100"
app:bar_style="transparent"
app:color_right="@color/colorAccent"
app:icon_back="false"
app:title=""
app:title_right="@string/login_register" />
<LinearLayout
android:id="@+id/rl_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#CCC"
>
<ImageView
android:layout_width="@dimen/space_200"
android:layout_height="@dimen/space_200"
android:layout_margin="@dimen/space_60"
android:src="@mipmap/ic_logo" />
<EditText
android:id="@+id/et_login_phone"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginTop="@dimen/space_20"
android:layout_marginRight="@dimen/space_80"
android:hint="@string/login_phone_input_hint"
android:inputType="phone"
android:maxLength="11"
android:maxLines="1" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginRight="@dimen/space_80" />
<EditText
android:id="@+id/et_login_password"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginTop="@dimen/space_40"
android:layout_marginRight="@dimen/space_80"
android:hint="@string/login_password_input_hint"
android:inputType="textPassword"
android:maxLength="20"
android:maxLines="1" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginRight="@dimen/space_80" />
<TextView
android:id="@+id/tv_login_forget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginTop="@dimen/space_30"
android:layout_marginRight="@dimen/space_120"
android:text="@string/login_forget"
android:textColor="@color/colorAccent" />
<Button
android:id="@+id/btn_login_commit"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_80"
android:layout_marginTop="@dimen/space_60"
android:layout_marginRight="@dimen/space_80"
android:text="@string/login_text" />
</LinearLayout>
</LinearLayout>
b: Activity 中处理:
@Override
public void onCreate() {
setContentView(R.layout.activity_login);
et_login_phone=findViewById(R.id.et_login_phone);
et_login_password=findViewById(R.id.et_login_password);
//SoftHideKeyBoardUtil.assistActivity(this);
//核心处理
addLayoutListener(findViewById(R.id.main),findViewById(R.id.rl_login));
}
/**
* 保持登录按钮始终不会被覆盖
*
* @param root
* @param subView
*/
public void addLayoutListener(final View root, final View subView) {
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
// 获取root在窗体的可视区域
root.getWindowVisibleDisplayFrame(rect);
// 获取root在窗体的不可视区域高度(被其他View遮挡的区域高度)
int rootInvisibleHeight = root.getRootView().getHeight() - rect.bottom;
// 若不可视区域高度大于200,则键盘显示,其实相当于键盘的高度
if (rootInvisibleHeight > 200) {
// 显示键盘时
int srollHeight = rootInvisibleHeight - (root.getBottom() - subView.getBottom()) - getNavigationBarHeight(root.getContext());
if (srollHeight > 0) {//当键盘高度覆盖按钮时
subView.scrollTo(0, srollHeight);
}
} else {
// 隐藏键盘时
subView.scrollTo(0, 0);
}
}
});
}
/**
* 判断是否有虚拟底部按钮
*
* @return
*/
public static boolean checkDeviceHasNavigationBar(Context context) {
boolean hasNavigationBar = false;
Resources rs = context.getResources();
int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
if (id > 0) {
hasNavigationBar = rs.getBoolean(id);
}
try {
Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
Method m = systemPropertiesClass.getMethod("get", String.class);
String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
if ("1".equals(navBarOverride)) {
hasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
hasNavigationBar = true;
}
} catch (Exception e) {
Log.w(TAG, e);
}
return hasNavigationBar;
}
/**
* 获取底部虚拟按键高度
*
* @return
*/
public static int getNavigationBarHeight(Context context) {
int navigationBarHeight = 0;
Resources rs = context.getResources();
int id = rs.getIdentifier("navigation_bar_height", "dimen", "android");
if (id > 0 && checkDeviceHasNavigationBar(context)) {
navigationBarHeight = rs.getDimensionPixelSize(id);
}
return navigationBarHeight;
}
adjustResize失效情况:activity设置了全屏属性指Theme.Light.NotittleBar.Fullscreen(键盘弹起时会将标题栏也推上去)或者设置了activity对应的主题中android:windowTranslucentStatus属性,设置方式为:android:windowTranslucentStatus=true,这时如果对应的页面上含有输入框,将会导致点击输入框时软键盘弹出后键盘覆盖输入框,导致输入框看不见。
fitsSystemWindows=”true”,只有初始的view起作用:如果在布局中不是最外层控件设置fitsSystemWindows=”true”, 那么设置的那个控件高度会多出一个状态栏高度。若有多个view设置了,因第一个view已经消耗掉insect,其他view设置了也会被系统忽略。
//点击done 按钮自动收回键盘:
<EditText
android:id="@+id/ssid"
android:layout_width="561dp"
android:layout_height="wrap_content"
android:text="@string/wifi_ssid"
android:textSize="24.0sp"
android:singleLine="true"
android:imeOptions="actionDone"
/>
参考设计: