您的位置:首页 > 移动开发 > Android开发

Android 模仿QQ登录界面解决软键盘遮挡问题

2016-09-21 13:58 726 查看
Android 软件盘弹出可能会遮挡住界面上的某些控件。当 windowSoftInputMode 为 adjustPan 时,一般不会挡住 EditText,但是假如 EditText 下面是一个登录按钮,那么这个按钮就可能被挡住,但有时我们希望用户输完密码可以直接点击登录按钮,而不用把软键盘收起来。这时就需要用到 adjustResize,这种模式能够获取到软键盘的高度,这样我们就能够精确的对界面进行控制。

在阅读本章之前,你应该了解 windowSoftInputMode 的一些属性,特别是 adjustResize,如果还不熟悉,建议先阅读Android 软键盘之 windowSoftInputMode 分析再回过头来继续往下看。

QQ 登录界面很好的解决了软键盘遮挡问题,当然在大屏手机上软键盘并不会挡住登录按钮。今天我们也来模仿一个 QQ 登录界面,最终效果如下:



监听软键盘弹出及收起事件

step1. 指定 windowSoftInputMode=”adjustResize”

在 AndroidManifest.xml 中相应的 Activity 设置 android:windowSoftInputMode=”adjustResize”,也可以在 java 代码中设置。

step2. 监听 contentView 宽高(layout) 变化

获取 ViewTreeObserver 并监听 OnGlobalLayoutListener。当然最好把这些代码独立出来放在某个帮助类。一开始我是用
View#addOnLayoutChangeListener
,同样可以监听软键盘弹出及收起,但是在 onLayoutChange 方法发起一个
requestLayout()
有时会出现一些问题。

看代码说话:

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);
}
}

public void onCreate() {
View content = activity.findViewById(android.R.id.content);
// content.addOnLayoutChangeListener(listener); 这个方法有时会出现一些问题
content.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}

public void onDestory() {
View content = activity.findViewById(android.R.id.content);
content.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}

private OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener() {

@Override
public void onGlobalLayout() {
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int newBlankheight = screenHeight - rect.bottom;
if (newBlankheight != blankHeight) {
if (newBlankheight > blankHeight) {
// keyboard pop
if (onKeyBoardStatusChangeListener != null) {
onKeyBoardStatusChangeListener.OnKeyBoardPop(newBlankheight);
}
} else { // newBlankheight < blankHeight
// keyboard close
if (onKeyBoardStatusChangeListener != null) {
onKeyBoardStatusChangeListener.OnKeyBoardClose(blankHeight);
}
}
}
blankHeight = newBlankheight;
}
};

public void setOnKeyBoardStatusChangeListener(
OnKeyBoardStatusChangeListener onKeyBoardStatusChangeListener) {
this.onKeyBoardStatusChangeListener = onKeyBoardStatusChangeListener;
}

public interface OnKeyBoardStatusChangeListener {

void OnKeyBoardPop(int keyBoardheight);

void OnKeyBoardClose(int oldKeyBoardheight);
}
}


实现 QQ 登录界面

有了这个 KeyBoardHelper,那么要实现和 QQ 登录界面一样的效果就不难了。我们甚至不需要任何自定义控件。思路是在软键盘弹出时,把登录按钮以上的布局往上移,只要为其设置一个负值的 topMargin 即可。

如图所示:



MainActivity 代码如下:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;

import com.example.qq.support.KeyBoardHelper;
import com.example.qq.support.KeyBoardHelper.OnKeyBoardStatusChangeListener;

public class MainActivity extends Activity {

private int bottomHeight;
private KeyBoardHelper boardHelper;
private View layoutBottom;
private View layoutContent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qq_login);

layoutContent = findViewById(R.id.layout_content);
layoutBottom = findViewById(R.id.layout_bottom);
boardHelper = new KeyBoardHelper(this);
boardHelper.onCreate();
boardHelper.setOnKeyBoardStatusChangeListener(onKeyBoardStatusChangeListener);
layoutBottom.post(new Runnable() {
@Override
public void run() {
bottomHeight = layoutBottom.getHeight();
}
});
}

private OnKeyBoardStatusChangeListener onKeyBoardStatusChangeListener = new OnKeyBoardStatusChangeListener() {

@Override
public void OnKeyBoardPop(int keyBoardheight) {

final int height = keyBoardheight;
if (bottomHeight > height) {
layoutBottom.setVisibility(View.GONE);
} else {
int offset = bottomHeight - height;
final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
.getLayoutParams();
lp.topMargin = offset;
layoutContent.setLayoutParams(lp);
}

}

@Override
public void OnKeyBoardClose(int oldKeyBoardheight) {
if (View.VISIBLE != layoutBottom.getVisibility()) {
layoutBottom.setVisibility(View.VISIBLE);
}
final ViewGroup.MarginLayoutParams lp = (MarginLayoutParams) layoutContent
.getLayoutParams();
if (lp.topMargin != 0) {
lp.topMargin = 0;
layoutContent.setLayoutParams(lp);
}

}
};

@Override
protected void onDestroy() {
super.onDestroy();
boardHelper.onDestory();
}
}


布局文件:activity_qq_login.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<LinearLayout
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="68dp"
android:focusable="true"
android:scaleType="centerInside"
android:src="@drawable/qq_ava"
android:visibility="visible" />

<LinearLayout
android:id="@+id/layout_ed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:background="#ffffff"
android:divider="@drawable/divider"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:showDividers="middle" >

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="QQ号/手机号/邮箱"
android:padding="10dp"
android:textColor="#000000"
android:textColorHint="#d2d2d2"
android:textCursorDrawable="@null" />

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:hint="密码"
android:padding="10dp"
android:textColor="#000000"
android:textColorHint="#d2d2d2"
android:textCursorDrawable="@null" />
</LinearLayout>

<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:layout_marginRight="14dp"
android:layout_marginTop="14dp"
android:background="@drawable/btn_login"
android:text="登陆"
android:textSize="17sp" />

<RelativeLayout
android:id="@+id/layout_bottom"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<TextView
android:id="@+id/tv_cannot_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="14dp"
android:text="无法登陆?"
android:textColor="@color/action_bar_bg"
android:textSize="14sp" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="14dp"
android:text="新用户"
android:textColor="@color/action_bar_bg"
android:textSize="14sp" />
</RelativeLayout>
</LinearLayout>

<include
android:id="@+id/appbar"
android:layout_width="fill_parent"
android:layout_height="50dp"
layout="@layout/appbar" />

</RelativeLayout>


点我下载源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: