小小草图不成敬意;
GIF图是效果,我确保忘记密码按钮也显示出来;
默认情况下,软键盘弹出来时会把登录按钮遮盖住,用户需要点击登录按钮时需要先隐藏软键盘;
使用android:windowSoftInputMode="adjustPan"也只是不让软键盘遮盖输入框,
需要把登录的按钮不被软键盘遮盖,只需要平移登录的Layout就行了;
在软键盘打开时把布局向上移,软键盘关闭时复位;位移的高度就是草图 Y2 - Y1;
可以仅移动登录Layout的布局,也可以移动最外层的rootView布局;
1、计算出登录Layout距离屏幕底部的高度:
layoutLogin.post(new Runnable() {
@Override
public void run() {
//不可以直接获取控件位置,放在这个里面获取;
int[] viewLocation = new int[2];
layoutLogin.getLocationOnScreen(viewLocation); //获取该控价在屏幕中的位置(左上角的点)
// loginViewtoBottom = UiUtils.getScreenHeight(mContext) - layoutLogin.getBottom(); //getBottom是该控件最底部距离父控件顶部的距离
loginViewtoBottom = UiUtils.getScreenHeight(mContext) - viewLocation[1] - layoutLogin.getHeight(); //屏幕高度-控件距离顶部高度-控件高度
}
});
2、计算出软键盘的高度、以及软键盘打开和关闭的监听:
下面这个时软键盘监听的工具类:
public class KeyBoardHelper {
private Activity activity;
private OnKeyBoardStatusChangeListener onKeyBoardStatusChangeListener;
private int screenHeight;
// 空白高度 = 屏幕高度 - 当前 Activity 的可见区域的高度
// 当 blankHeight 不为 0 即为软键盘高度。
private int blankHeight = 0;
public KeyBoardHelper(Activity activity) {
this.activity = activity;
screenHeight = activity.getResources().getDisplayMetrics().heightPixels;
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
if (activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
View content = activity.findViewById(android.R.id.content);
content.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void onDestory() {
View content = activity.findViewById(android.R.id.content);
content.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int newBlankheight = screenHeight - rect.bottom;
if (newBlankheight != blankHeight) {
if(newBlankheight==0){
// keyboard close
if (onKeyBoardStatusChangeListener != null) {
// onKeyBoardStatusChangeListener.OnKeyBoardClose(newBlankheight);
onKeyBoardStatusChangeListener.OnKeyBoardClose(blankHeight);
}
}else{
// keyboard pop
if (onKeyBoardStatusChangeListener != null) {
onKeyBoardStatusChangeListener.OnKeyBoardPop(newBlankheight);
}
}
}
blankHeight = newBlankheight;
}
};
public void setOnKeyBoardStatusChangeListener(
OnKeyBoardStatusChangeListener onKeyBoardStatusChangeListener) {
this.onKeyBoardStatusChangeListener = onKeyBoardStatusChangeListener;
}
public interface OnKeyBoardStatusChangeListener {
void OnKeyBoardPop(int keyBoardheight);
void OnKeyBoardClose(int oldKeyBoardheight);
}
}
3、在Activity中监听软键盘的打开关闭、登录Layout做平移动画;
软键盘的高度 - 登录Layout距离屏幕底部高度 = 动画位移距离;
KeyBoardHelper keyBoardHelper = new KeyBoardHelper(this);
keyBoardHelper.setOnKeyBoardStatusChangeListener(new KeyBoardHelper.OnKeyBoardStatusChangeListener() {
@Override
public void OnKeyBoardPop(int keyBoardheight) {
L.i(keyBoardheight + "--open");
// rootView.scrollTo(0, keyBoardheight - loginViewtoBottom);
if (animatorUp == null) { //如果每次弹出的键盘高度不一致,就不要这个判断,每次都新创建动画(密码键盘可能和普通键盘高度不一致)
int translationY = keyBoardheight - loginViewtoBottom;
animatorUp = ObjectAnimator.ofFloat(layoutLogin, "translationY", 0, -translationY);
animatorUp.setDuration(360);
animatorUp.setInterpolator(new AccelerateDecelerateInterpolator());
}
animatorUp.start();
}
@Override
public void OnKeyBoardClose(int oldKeyBoardheight) {
L.i(oldKeyBoardheight + "--close");
// rootView.scrollTo(0, 0);
if (animatorDown == null) {//如果每次弹出的键盘高度不一致,就不要这个判断,每次都新创建动画(密码键盘可能和普通键盘高度不一致)
int translationY = oldKeyBoardheight - loginViewtoBottom;
animatorDown = ObjectAnimator.ofFloat(layoutLogin,"translationY",-translationY, 0);
animatorDown.setDuration(360);
animatorDown.setInterpolator(new AccelerateDecelerateInterpolator());
}
animatorDown.start();
}
});
好了大功告成!!!
下面时全部代码,有兴趣的可以看看:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_height="match_parent"
android:id="@+id/rootView"
tools:context=".activity.login.LoginActivity">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/login_bg"
android:scaleType="centerCrop"
/>
<include layout="@layout/layout_bar" />
<LinearLayout
android:id="@+id/layoutLogin"
android:orientation="vertical"
android:paddingTop="120dp"
android:layout_marginRight="@dimen/distance"
android:layout_marginLeft="@dimen/distance"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_marginLeft="22dp"
android:layout_marginRight="22dp"
android:layout_width="match_parent"
android:layout_height="51dp">
<View
android:layout_width="match_parent"
android:background="@color/line"
android:layout_alignParentBottom="true"
android:layout_height="1dp"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/etPhone"
android:layout_width="wrap_content"
android:minWidth="100dp"
android:layout_centerInParent="true"
android:textSize="16dp"
android:hint="请输入手机号码"
android:background="@null"
android:inputType="number"
android:textColor="@color/main_white"
android:textColorHint="@color/adadaa"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:layout_marginLeft="22dp"
android:layout_marginRight="22dp"
android:layout_width="match_parent"
android:layout_height="51dp">
<View
android:layout_width="match_parent"
android:background="@color/line"
android:layout_alignParentBottom="true"
android:layout_height="1dp"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/etPwd"
android:layout_width="wrap_content"
android:minWidth="100dp"
android:layout_centerInParent="true"
android:textSize="16dp"
android:hint="请输入登录密码"
android:password="true"
android:inputType="textPassword"
android:background="@null"
android:textColor="@color/main_white"
android:textColorHint="@color/adadaa"
android:layout_height="match_parent" />
</RelativeLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_marginRight="44dp"
android:layout_marginLeft="44dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="登录"
android:foreground="?android:attr/selectableItemBackground"
android:gravity="center"
android:layout_gravity="center"
android:textSize="15dp"
android:textColor="#292929"
android:background="@drawable/btn_golden_radius"
/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_marginRight="44dp"
android:layout_marginLeft="44dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="注册"
android:gravity="center"
android:layout_gravity="center"
android:textSize="15dp"
android:textColor="#292929"
android:foreground="?android:attr/selectableItemBackground"
android:background="@drawable/btn_golden_radius"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="忘记密码"
android:padding="20dp"
android:layout_gravity="center_horizontal"
android:textColor="#ffffffff"
android:gravity="center"
android:textSize="14dp"
android:foreground="?android:attr/selectableItemBackground"
/>
</LinearLayout>
</RelativeLayout>
Activity中的initList函数:
private int loginViewtoBottom;
private ObjectAnimator animatorUp,animatorDown;
@Override
protected void initList() {
layoutLogin.post(new Runnable() {
@Override
public void run() {
//不可以直接获取控件位置,放在这个里面获取;
int[] viewLocation = new int[2];
layoutLogin.getLocationOnScreen(viewLocation); //获取该控价在屏幕中的位置(左上角的点)
// loginViewtoBottom = UiUtils.getScreenHeight(mContext) - layoutLogin.getBottom(); //getBottom是该控件最底部距离父控件顶部的距离
loginViewtoBottom = UiUtils.getScreenHeight(mContext) - viewLocation[1] - layoutLogin.getHeight(); //屏幕高度-控件距离顶部高度-控件高度
}
});
KeyBoardHelper keyBoardHelper = new KeyBoardHelper(this);
keyBoardHelper.setOnKeyBoardStatusChangeListener(new KeyBoardHelper.OnKeyBoardStatusChangeListener() {
@Override
public void OnKeyBoardPop(int keyBoardheight) {
L.i(keyBoardheight + "--open");
// rootView.scrollTo(0, keyBoardheight - loginViewtoBottom);
if (animatorUp == null) { //如果每次弹出的键盘高度不一致,就不要这个判断,每次都新创建动画(密码键盘可能和普通键盘高度不一致)
int translationY = keyBoardheight - loginViewtoBottom;
animatorUp = ObjectAnimator.ofFloat(layoutLogin, "translationY", 0, -translationY);
animatorUp.setDuration(360);
animatorUp.setInterpolator(new AccelerateDecelerateInterpolator());
}
animatorUp.start();
}
@Override
public void OnKeyBoardClose(int oldKeyBoardheight) {
L.i(oldKeyBoardheight + "--close");
// rootView.scrollTo(0, 0);
if (animatorDown == null) {//如果每次弹出的键盘高度不一致,就不要这个判断,每次都新创建动画(密码键盘可能和普通键盘高度不一致)
int translationY = oldKeyBoardheight - loginViewtoBottom;
animatorDown = ObjectAnimator.ofFloat(layoutLogin,"translationY",-translationY, 0);
animatorDown.setDuration(360);
animatorDown.setInterpolator(new AccelerateDecelerateInterpolator());
}
animatorDown.start();
}
});
}
涉及到的一些工具类(获取屏幕高度)可以自己实现;