最近把Android应用的一些组件替换掉,发现虚拟按键会遮挡布局。查了一下,发现是页面布局的可用高度不是视图的实际高度,只需要把页面布局的高度重新设置即可。
原文:Android虚拟按键遮挡布局【完美解决方案】
/**
* Created by : vince
* Created at : 2019/12/20
* Desc : 解决虚拟按键遮挡页面布局问题
* Usage : 在需要重新布局的Activity的onCreate方法关联视图:AndroidVirtualKey.assistActivity(findViewById(android.R.id.xxx), this)
*/
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import java.lang.reflect.Method;
public class AndroidVirtualKey {
private View mViewObserved;//被监听的视图
private int usableHeightPrevious;//视图变化前的可用高度
private ViewGroup.LayoutParams frameLayoutParams;
private AndroidVirtualKey(View viewObserving, final Activity activity) {
mViewObserved = viewObserving;
//给View添加全局的布局监听器
mViewObserved.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
resetLayoutByUsableHeight(activity);
}
});
frameLayoutParams = mViewObserved.getLayoutParams();
}
/**
* 关联要监听的视图
*/
public static void assistActivity(View viewObserving, Activity activity) {
new AndroidVirtualKey(viewObserving, activity);
}
/**
* 重新设置页面布局
* @param activity
*/
private void resetLayoutByUsableHeight(Activity activity) {
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
//得到wm所管理屏幕(Display)的分辨率
int width = wm.getDefaultDisplay().getWidth();
int height = wm.getDefaultDisplay().getHeight();
int usableHeightNow = height;
/**
* 比较布局变化前后的View的可用高度,如果两次高度不一致
* 将当前的View的可用高度设置成View的实际高度;如一致
* 则无需改变
*/
if (usableHeightNow != usableHeightPrevious) {
mViewObserved.setPadding(0, 0, 0, getHasVirtualKey(activity)); //改变内边距padding-bottom
mViewObserved.requestLayout();//请求重新布局
usableHeightPrevious = usableHeightNow;
}
}
/**
* dpi 通过反射,获取包含虚拟键的整体屏幕高度
* height 获取屏幕尺寸,但是不包括虚拟功能高度
*
* @return
*/
public static int getHasVirtualKey(Activity activity) {
int dpi = 0;
Display display = activity.getWindowManager().getDefaultDisplay(); //得到屏幕
DisplayMetrics dm = new DisplayMetrics();
@SuppressWarnings("rawtypes")
Class c;
try {
c = Class.forName("android.view.Display");
@SuppressWarnings("unchecked")
Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
method.invoke(display, dm);
dpi = dm.heightPixels;
} catch (Exception e) {
e.printStackTrace();
}
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
return dpi - height;
}
}