App开发中遇到整个应用或某些界面需要沉侵式效果,迎面而来的就是各种适配兼容问题。本文主要针对如何适配全屏/沉侵式模式下–输入框被键盘遮挡及虚拟导航遮挡底部问题。
1、适配全屏/沉侵式模式下–输入框被键盘遮挡问题(原理就是对contentView的高度进行处理):
public class LayoutAutoResizeHelper {
private int usableHeightPrevious;
private LayoutAutoResizeHelper() {
}
public static LayoutAutoResizeHelper getInstance() {
return InstanceHolder.INSTANCE;
}
private static class InstanceHolder {
private static final LayoutAutoResizeHelper INSTANCE = new LayoutAutoResizeHelper();
}
public void adjustResize(Activity activity) {
setupAdjustResize(activity);
}
private void setupAdjustResize(Activity activity) {
ViewGroup content = activity.findViewById(android.R.id.content);
View contentView = content.getChildAt(0);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent(contentView);
}
});
}
private void possiblyResizeChildOfContent(View contentView) {
ViewGroup.LayoutParams contentViewParams = contentView.getLayoutParams();
//获取当前界面可视区域(注:可视区域指APP界面)
Rect rect = computeUsableRect(contentView);
//获取当前界面可视区域高度
int currentUsableHeight = rect.bottom - rect.top;
if (currentUsableHeight != usableHeightPrevious) {
//获取根布局高度
int rootViewHeight = contentView.getRootView().getHeight();
//计算出根布局高度与可视区域高度差值
int heightDiff = rootViewHeight - currentUsableHeight;
//差值超过四分之一说明软键盘弹出
if (heightDiff > (rootViewHeight / 4)) {
//全屏模式需要加上状态栏高度,否则低于软键盘高度的输入框弹起时与软键盘顶部会有偏差
contentViewParams.height = rootViewHeight - heightDiff + getStatusHeight(contentView.getContext());
} else {
contentViewParams.height = rootViewHeight ;
}
contentView.requestLayout();
usableHeightPrevious = currentUsableHeight;
}
}
private Rect computeUsableRect(View view) {
Rect r = new Rect();
view.getWindowVisibleDisplayFrame(r);
return r;
}
private int getStatusHeight(Context context) {
return ScreenUtils.getStatusHeight(context);
}
}
2.适配全屏/沉侵式模式下–虚拟导航遮挡底部问题(问题描述:在问题1的基础之上,当软键盘收起的如果底部存在虚拟导航按键,此时虚拟导航遮挡底部)。这个问题我们只需要修改一下问题1方案中的possiblyResizeChildOfContent()方法即可。
private void possiblyResizeChildOfContent(View contentView) {
ViewGroup.LayoutParams contentViewParams = contentView.getLayoutParams();
//获取当前界面可视区域(注:可视区域指APP界面)
Rect rect = computeUsableRect(contentView);
//获取当前界面可视区域高度
int currentUsableHeight = rect.bottom - rect.top;
if (currentUsableHeight != usableHeightPrevious) {
//获取根布局高度
int rootViewHeight = contentView.getRootView().getHeight();
//计算出根布局高度与可视区域高度差值
int heightDiff = rootViewHeight - currentUsableHeight;
//差值超过四分之一说明软键盘弹出
if (heightDiff > (rootViewHeight / 4)) {
//全屏模式需要加上状态栏高度,否则低于软键盘高度的输入框弹起时与软键盘顶部会有偏差
contentViewParams.height = rootViewHeight - heightDiff + getStatusHeight(contentView.getContext());
} else {
//此处需要使用rect.bottom ,因为部分手机有虚拟导航且处于开启状态时会导致底部界面被虚拟导航遮挡
contentViewParams.height = rect.bottom;
}
contentView.requestLayout();
usableHeightPrevious = currentUsableHeight;
}
}
3、附上获取状态栏高度的方法
public static int getStatusHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}