登录是每一个APP必备的功能,我观察了很多的APP,发现登录的账号密码编辑时,对软键盘弹起后的处理并不是很好,在弹起软键盘时,登录按钮会被遮住了,需要手动将软键盘收回,才可以点击登录按钮,这无疑使用户多操作了一步。
下面我随便找了几个没对软键盘弹起后做处理的APP。
其实这个问题,可以用一个ScrollView来解决,包裹住需要往上移动的部分布局,在弹起软键盘的时候,将ScrollView滚动到对应编辑框所属的ViewGroup上即可,代码我已经写好了,其实就几行关键代码,直接上代码。
package com.ysbing.loginscrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ScrollView;
/**
* 对编辑框做软键盘弹起适配
*/
public class LoginScrollView extends ScrollView {
private int mDefaultBottom = -1;
private View mChangeView;
public LoginScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
post(new Runnable() {
@Override
public void run() {
addListener(LoginScrollView.this, 0);
}
});
}
private void addListener(ViewGroup viewGroup, int layer) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if (view instanceof EditText) {
View childParent = view;
for (int j = 2; j < layer; j++) {
childParent = (View) childParent.getParent();
}
final View finalChildParent = childParent;
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mChangeView = finalChildParent;
scrollTo(0, finalChildParent.getTop());
}
});
} else if (view instanceof ViewGroup) {
addListener((ViewGroup) view, layer + 1);
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (b >= mDefaultBottom) {
mDefaultBottom = b;
} else {
if (mChangeView != null) {
smoothScrollTo(0, mChangeView.getTop());
}
}
}
}复制代码
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ysbing.loginscrollview.LoginScrollView
android:id="@+id/loginScrollView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="22dp"
android:layout_marginStart="22dp"
android:paddingBottom="4dp"
android:paddingTop="100dp">
<TextView
android:id="@+id/login_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="26dp"
android:text="手机密码登录"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/login_textview2"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_marginTop="28dp"
android:gravity="center"
android:text="+86"
android:textColor="#d8d8d8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login_textview" />
<View
android:id="@+id/login_view"
android:layout_width="0.5dp"
android:layout_height="20dp"
android:layout_marginLeft="25dp"
android:layout_marginStart="25dp"
app:layout_constraintBottom_toBottomOf="@+id/login_textview2"
app:layout_constraintStart_toEndOf="@+id/login_textview2"
app:layout_constraintTop_toTopOf="@+id/login_textview2" />
<EditText
android:id="@+id/login_et_account"
android:layout_width="0dp"
android:layout_height="0dp"
android:ems="10"
android:hint="请输入有效手机号"
android:inputType="phone"
android:maxLength="11"
android:paddingLeft="20dp"
android:paddingStart="20dp"
app:layout_constraintBottom_toBottomOf="@+id/login_textview2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toEndOf="@+id/login_view"
app:layout_constraintTop_toTopOf="@+id/login_textview2" />
<View
android:id="@+id/login_view2"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:background="#e5e5e5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login_textview2" />
<EditText
android:id="@+id/login_et_pwd"
android:layout_width="0dp"
android:layout_height="60dp"
android:ems="10"
android:hint="请输入8-16位长度密码"
android:inputType="textPassword"
android:maxLength="16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login_view2" />
<View
android:id="@+id/login_view3"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:background="#e5e5e5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login_et_pwd" />
<Button
android:id="@+id/login_btn_ok"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginTop="42dp"
android:text="登录"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/login_view3" />
</android.support.constraint.ConstraintLayout>
</com.ysbing.loginscrollview.LoginScrollView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="22dp"
android:layout_marginStart="22dp"
android:text="忘记密码"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/loginScrollView" />
</android.support.constraint.ConstraintLayout>复制代码
上面的代码复制就可以使用,我就不放到Github上了,下面解释下代码。
看代码中的addListener方法,这个是最核心的部分,看参数,传入了两个参数,第一个参数ViewGroup是用来遍历,第二个参数layer是表示遍及进入了第几层。
在遍历ViewGroup的子View,寻找出ViewGroup中所有的EditText,找到后给EditText加上监听,用于软键盘弹起时滚动ScrollView,这里还有一个需要注意的地方,需要将ScrollView滚动到哪个位置才合适呢?layer在这里起作用了,用来寻找出该EditText所属的ViewGroup,然后将ScrollView滚动到该ViewGroup的顶部,就大功告成了。
XML布局代码就不解释了,还有一个需要注意的是,需要在manifest文件将该Activity添加android:windowSoftInputMode="adjustResize|stateHidden"
windowSoftInputMode在这里也不想多说,另行查资料去。
有兴趣的同学,复制上面的代码运用到项目里吧,最后看看成果。