前言
公司最近要适配华为Pro20,没办法 – 。–
一、AndroidP的适配方案
上来我最先找到的就是AndroidP,就先以这个入手了。
首先看下谷歌给出的api,大致就分为两种。
1.设置全屏模式
WindowManager.LayoutParams lp
=getWindow().getAttributes();
lp.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
getWindow().setAttributes(lp);
新的布局属性 layoutInDisplayCutoutMode 包含三种可选的模式,
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 1;
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
2.获取刘海屏
view.postDelayed(new Runnable() {
@Override
public void run() {
DisplayCutout displayCutout = view.getRootWindowInsets().getDisplayCutout();
Log.i("cxmyDev", "SafeInsetBottom:" + displayCutout.getSafeInsetBottom());
Log.i("cxmyDev", "SafeInsetLeft:" + displayCutout.getSafeInsetLeft());
Log.i("cxmyDev", "SafeInsetRight:" + displayCutout.getSafeInsetRight());
Log.i("cxmyDev", "SafeInsetTop:" + displayCutout.getSafeInsetTop());
}
}, 100);
刘海屏的凹槽,就在屏幕的中间,所以只有 getSafeInsetTop() 方法返回的结果,是我们需要的,而其他的 getSafeInsetXxx() 方法,直接返回的是 0 。
这里有人说了,没有华为Pro20怎么办?当然不能买一个!那多费钱,我们可以下载模拟器。
在模拟器中,可以通过开发者选项里的 “Simulate a display with a cutout”,开启刘海屏的支持。
你们以为解决了么,遗憾的告诉你们并没有。
你们看下我写到程序的代码如下:
Util.logv("Util", "SDK_INT:" + Build.VERSION.SDK_INT);
DisplayCutout displayCutout = null;
if (Build.VERSION.SDK_INT >= 28) {
displayCutout = new View(this).getRootWindowInsets().getDisplayCutout();
Util.logv("Util", "SafeInsetBottom:" + displayCutout.getSafeInsetBottom());
Util.logv("Util", "SafeInsetLeft:" + displayCutout.getSafeInsetLeft());
Util.logv("Util", "SafeInsetRight:" + displayCutout.getSafeInsetRight());
Util.logv("Util", "SafeInsetTop:" + displayCutout.getSafeInsetTop());
}
可以看出SDK_INT >=28 才会走DisplayCutout 的相关方法,而上面我打的log显示的SDK_INT =27这根本走不通。起初我以为是模拟器的问题,于是我是华为的平台上用远程真机Pro20测试,发现SDK_INT 也是等于27,于是此路不通。
原因估计如下:
(1)O版本适配:谷歌未提供统一方案,需要使用华为提供的刘海屏SDK进行适配,同时华为刘海屏SDK方案
也会继承到华为P版本,在华为P版本中将同时支持两种方案:华为O版本方案+谷歌P版本方案;
(2)P版本适配:谷歌已经提供统一的适配方案,建议应用采用谷歌统一的方案进行适配。
也就是说不能用谷歌的api解决华为Pro20的问题。
二、手机厂商的适配API
第一条路不通,于是我改变思路,这次是适配华为Pro20 ,既然谷歌不可以,那么华为有没给对应的适配方案呢?不出我们所料是有的,我还顺便找了VOIO和oppod的。
华为:
http://mini.eastday.com/bdmip/180411011257629.html
oppo:
https://open.oppomobile.com/wiki/doc#id=10139
voio:
https://dev.vivo.com.cn/doc/document/info?id=103
实现原理都是一样的利用反射调用对应的api方法。
代码都给你写好了,≡(▔﹏▔)≡
/**
*华为start
*/
//判断是否是华为刘海屏
public static boolean hasNotchInScreen(Context context)
{
boolean ret = false;
try {
ClassLoader cl = context.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
ret = (boolean) get.invoke(HwNotchSizeUtil);
} catch (ClassNotFoundException e)
{ Log.e("test", "hasNotchInScreen ClassNotFoundException"); }
catch (NoSuchMethodException e)
{ Log.e("test", "hasNotchInScreen NoSuchMethodException"); }
catch (Exception e)
{ Log.e("test", "hasNotchInScreen Exception"); }
finally
{ return ret; }
}
//获取华为刘海的高宽
public static int[] getNotchSize(Context context) {
int[] ret = new int[]{0, 0};
try {
ClassLoader cl = context.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("getNotchSize"); ret = (int[]) get.invoke(HwNotchSizeUtil);
} catch (ClassNotFoundException e) {
Log.e("test", "getNotchSize ClassNotFoundException"); }
catch (NoSuchMethodException e)
{ Log.e("test", "getNotchSize NoSuchMethodException"); }
catch (Exception e) { Log.e("test", "getNotchSize Exception"); }
finally { return ret; }
}
//全屏显示 暂时不能用
public static final int FLAG_NOTCH_SUPPORT=0x00010000;
@TargetApi(Build.VERSION_CODES.KITKAT)
public static void setFullScreenWindowLayoutInDisplayCutout(Window window) {
if (window == null) { return; }
WindowManager.LayoutParams layoutParams = window.getAttributes();
try
{
Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");
Constructor con=layoutParamsExCls.getConstructor(WindowManager.LayoutParams.class);
Object layoutParamsExObj=con.newInstance(layoutParams);
Method method=layoutParamsExCls.getMethod("addHwFlags", int.class);
method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);
}
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |InstantiationException | InvocationTargetException e)
{ Log.e("test", "hw notch screen flag api error"); }
catch (Exception e) { Log.e("test", "other Exception"); }
}
/**
*华为end
*/
/**
*Oppo start
*/
public static boolean hasNotchInScreenAtOppo(Context context){
return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
}
/**
*Oppo end
*/
/**
*voio start
*/
public static final int NOTCH_IN_SCREEN_VOIO=0x00000020;//是否有凹槽
public static final int ROUNDED_IN_SCREEN_VOIO=0x00000008;//是否有圆角
public static boolean hasNotchInScreenAtVoio(Context context){
boolean ret = false;
try {
ClassLoader cl = context.getClassLoader();
Class FtFeature = cl.loadClass("com.util.FtFeature");
Method get = FtFeature.getMethod("isFeatureSupport",int.class);
ret = (boolean) get.invoke(FtFeature,NOTCH_IN_SCREEN_VOIO);
} catch (ClassNotFoundException e)
{ Log.e("test", "hasNotchInScreen ClassNotFoundException"); }
catch (NoSuchMethodException e)
{ Log.e("test", "hasNotchInScreen NoSuchMethodException"); }
catch (Exception e)
{ Log.e("test", "hasNotchInScreen Exception"); }
finally
{ return ret; }
}
/**
*voio end
*/
具体使用,就看你们的具体需求了。
总结:不要死钻牛角尖,试试换个思路。