做项目的时候有个要求:低部的按钮,要在用户输入的时候,悬浮在软键盘的上面,效果如下所示
初步的实现方案
anroid中有一个属性android:windowSoftInputMode,是专门处理软键盘在界面中显示的各种问题,刚开始我也是一下子想到了这个方法,如果对android:windowSoftInputMode这个属性不熟悉的话,可以先看一下下面的截图(来源于:https://blog.csdn.net/twoicewoo/article/details/7384398)
在AndroidManifest文件中配置如下代码:
android:windowSoftInputMode="adjustResize"
效果如下:
是不是感觉so easy,有没有?其实经过测试我发现如果我这个Activity,有加载Theme主题样式的:
样式里面有一个背景图片:
那么在点击隐藏软键盘的时候,会出现如下的效果:
卧槽,可以看见底部的背景图片了,其实上面的写法属于极端的例子了,因为我效果图中页面都跟背景图搭不上边,所以这个Activity中可以不加这个背景图,效果就杠杆的!如果非要解决上面的情况,请看下面的第二种方法。
第二种实现方案
1、布局代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/style_match_parent_white_bg"
android:orientation="vertical"
android:id="@+id/mRootView"
tools:context="com.tecsun.tsb.tosharetreasure.activity.login.PerfectDataActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/layout_genal_tool_bar"/>
<EditText
android:layout_gravity="center"
android:layout_margin="15dp"
android:id="@+id/et_login_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/please_input_login_name"
android:textColorHint="@color/CCCCCC"
android:textColor="@color/black"
android:background="@drawable/bg_edittext_select"
android:singleLine="true"
android:padding="@dimen/dp_4"
/>
<EditText
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
android:id="@+id/et_birth_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/tip_birth_date"
android:textColorHint="@color/CCCCCC"
android:textColor="@color/black"
android:background="@drawable/bg_edittext_select"
android:singleLine="true"
android:padding="@dimen/dp_4"
android:drawableRight="@mipmap/ic_select_arrow"
/>
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<RadioButton
android:id="@+id/btnMan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
android:textColor="@color/black"
android:checked="true"/>
<RadioButton
android:id="@+id/btnWoman"
android:layout_marginLeft="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="女"/>
</RadioGroup>
<EditText
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="设置密码(6-18位)"
android:textColorHint="@color/CCCCCC"
android:textColor="@color/black"
android:background="@drawable/bg_edittext_select"
android:singleLine="true"
android:padding="@dimen/dp_4"
/>
</LinearLayout>
<Button
android:layout_alignParentBottom="true"
android:id="@+id/bt_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启旅程"
android:textColor="@android:color/white"
android:background="@color/c_blue_2"
/>
</RelativeLayout>
注意点:
一定要获取布局的根布局
1、WindowManagerUtils工具类
public class WindowManagerUtils {
/**
* 获取屏幕的宽度
* @return
*/
public static int getScreenWidth(){
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
return width;
}
/**
* 获取屏幕的高度
* @return
*/
public static int getScreenHight(){
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
int height = wm.getDefaultDisplay().getHeight();
return height;
}
/**
* 获取屏幕的高度的一半
* @return
*/
public static int getScreenPartHight(){
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
int height = wm.getDefaultDisplay().getHeight();
return height/2;
}
}
2、实现的核心代码
@BindView(R.id.mRootView)
RelativeLayout mRootView;
/**
* 初始化监听的方法
*/
private void initListener() {
showInputManager(etLoginName);
showInputManager(etBirthDate);
showInputManager(etPwd);
}
/**
*
* @param editText
*/
private void showInputManager(EditText editText) {
editText.setFocusable(true);
editText.setFocusableInTouchMode(true);
editText.requestFocus();
/** 目前测试来看,还是挺准的
* 原理:OnGlobalLayoutListener 每次布局变化时都会调用
* 界面view 显示消失都会调用,软键盘显示与消失时都调用
* */
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutChangeListener);
InputMethodManager inputManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
ViewTreeObserver.OnGlobalLayoutListener mLayoutChangeListener = new ViewTreeObserver
.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//判断窗口可见区域大小
Rect r = new Rect();
// getWindowVisibleDisplayFrame()会返回窗口的可见区域高度
getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
//如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。
int heightDifference = WindowManagerUtils.getScreenHight() - (r.bottom);
boolean isKeyboardShowing = heightDifference > WindowManagerUtils.getScreenHight() / 3;
if (isKeyboardShowing) {
// bottomView 需要跟随软键盘移动的布局
// setDuration(0) 默认300, 设置 0 ,表示动画执行时间为0,没有过程,只有动画结果了
btStart.animate().translationY(-heightDifference).setDuration(0).start();
} else {
btStart.animate().translationY(0).start();
}
}
};
这种动态测量高度的变化,其实更适合于多变的环境中,我比较倾向于第二种,这样就不用对着第一种的各个属性在那里一个个测试效果,看是不是适合,呜呜呜........