1.前言
最近在开发一个小说阅读器APP,在阅读界面碰到了适配问题,把解决问题的方法及过程记录一下。因为我只有小米8一个测试机,所以方法不保证其他手机的兼容性,只是提供一个思路,希望能给到其他人帮助。
2.全面屏适配
在Android 7.0以后,google提供了在通过在AndroidManifest.xml文件中进行声明android:resizeableActivity = “true” 来开启分屏模式的开关,且自动适应了全面屏。此外,我们可以手动设置最大屏幕宽高比。
android8.0及以上:
<activity android:maxAspectRatio="2.1">...
</activity>
android7.1及以下版本:
<meta-data android:name="android.max_aspect" android:value="2.1" />
value值需要大于等于2.1,需要注意的是,如果手动进行设置了最大宽高比,一定要将多窗口模式设置为false,否则不生效。
3.刘海屏适配
从Android P开始,google提供了刘海屏适配的方案,提供了全新的 DisplayCutout
类,通过 DisplayCutout
类可以确定非功能区域的位置和形状。我们可以通过使用DisplayCutout
类中的getSafeInsetLeft ()、getSafeInsetRight ()、getSafeInsetTop ()、getSafeInsetBottom ()来分别获取安全区域距离屏幕左边、右边、上方、下方的距离,单位是px。
View decorView = getWindow().getDecorView();decorView.post(new Runnable() {@Overridepublic void run() {DisplayCutout displayCutout = decorView.getRootWindowInsets().getDisplayCutout();displayCutout.getSafeInsetLeft();displayCutout.getSafeInsetRight();displayCutout.getSafeInsetTop();displayCutout.getSafeInsetBottom();
});
除此此外,从Android P开始,google在WindowManager中新增了layoutInDisplayCutoutMode 布局参数属性,包含三种模式:
//默认情况,全屏页面不可用刘海区域,非全屏页面可以进行使用
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
//不允许使用刘海区域
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
//允许页面延伸到刘海区域
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1;
因为我需要开发的是一个小说阅读界面,使用刘海区域会导致不太美观,因此我采用了不允许使用刘海区域 的模式。
4.小米8(MIUI10)获取宽高
在开发小说阅读界面时,因为界面的绘制是通过获取屏幕的宽高来实现的,所以需要获取手机的宽和高。网上较多获取宽高的方法是通过下面实现的:
WindowManager manager = this.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int width = outMetrics.widthPixels;
int height = outMetrics.heightPixels;
int density = outMetrics.density;
但是使用该方法获取宽高后,在我的手机下方会出现一个黑条,很不美观。原因是因为该方法获取的是去除虚拟按键(导航栏)后的宽高,因为我的手机是使用的全面屏手势,没有使用虚拟按键,因此我们需要使用
manager.getDefaultDisplay().getRealMetrics(outMetrics);
来获取包含虚拟按键的宽高。
但是因为前面所说,我使用了不允许使用刘海屏的模式,因此会造成View下移,出现View超出屏幕的情况。我们知道是因为刘海屏的问题造成的,因此我们只需要去除刘海屏的高度便可以了。
此外,因为Build.VERSION.SDK_INT >= 28 时,才能调用官方接口,因此我们可以减去状态栏高度的方法进行适配,但是此方法仅适用于刘海屏高度小于状态栏高度的问题。
WindowManager manager = this.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int tempWidth = outMetrics.widthPixels;
int tempHeight = outMetrics.heightPixels;
int tempDensity = outMetrics.density;
int resourceId = BookApp.mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId >0 && resourceId != null) {int statusBarHeight = BookApp.mContext.getResources().getDimensionPixelSize(resourceId);if (statusBarHeight!=null)tempHeight = (int)(tempHeight- (statusBarHeight / tempDensity + 0.5f)); //将dip转为px然后减去
}