手机厂商一群弄潮儿,每次都能玩出新花样,各种奇形怪状的手机屏幕,为了增加玩家的沉浸感,我们开发游戏的话必须对异性屏幕进行适配。
一般安卓方法适配其实网上有很多方案了,主流的一套还是谷歌官方的接口,挖孔屏
首先是安卓p版本(apilv 28)以下的适配
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P){String result = getNotchByManufacturer();return;}
public static String getNotchByManufacturer(){Context context = UnityPlayer.currentActivity;String manufacturer = Build.MANUFACTURER.toLowerCase();String result = MANU_NONE;if(TextUtils.equals(manufacturer, "huawei")){if (hasNotchInHuawei(context))result = NOTCH_TYPE_HUAWEI;}else if(TextUtils.equals(manufacturer, "xiaomi")){if (hasNotchInMIUI(context))result = NOTCH_TYPE_MIUI;}else if(TextUtils.equals(manufacturer, "oppo")){if (hasNotchInOppo(context))result = NOTCH_TYPE_OPPO;}else if(TextUtils.equals(manufacturer, "vivo")){if (hasNotchInVivo(context))result = NOTCH_TYPE_VIVO;}else if(TextUtils.equals(manufacturer, "smartisan")){if (hasNotchInSmart(context))result = NOTCH_TYPE_SMART;}elseresult = ApiUnsupported;return result;}
一般手机厂商都会给适配方案的
<meta-data
android:name="notch.config"
android:value="portrait|landscape"/>
使用该接口。在 Application 下增加一个 meta-data,是否使用耳朵区域
华为:https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114
小米:https://dev.mi.com/console/doc/detail?pId=1293
Oppo:https://open.oppomobile.com/service/message/detail?id=61876
Vivo:https://dev.vivo.com.cn/documentCenter/doc/103
public static boolean hasNotchInMIUI(Context context){try{return SystemProperties.getInt("ro.miui.notch", 0) == 1;}catch(Exception e){e.printStackTrace();}return false;}/*** OPPO** @param context Context* @return hasNotch*/public static boolean hasNotchInOppo(Context context){return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");}/*** VIVO* <p>* android.util.FtFeature* public static boolean isFeatureSupport(int mask);* <p>* 参数:* 0x00000020表示是否有凹槽;* 0x00000008表示是否有圆角。** @param context Context* @return hasNotch*/private static int VIVO_NOTCH = 0x00000020;//是否有刘海private static int VIVO_FILLET = 0x00000008;//是否有圆角public static boolean hasNotchInVivo(Context context){boolean hasNotch = false;try{ClassLoader cl = context.getClassLoader();Class FtFeature = cl.loadClass("android.util.FtFeature");Method method = FtFeature.getMethod("isFeatureSupport", int.class);hasNotch = (boolean) method.invoke(FtFeature, VIVO_NOTCH);}catch (Exception e){e.printStackTrace();}return hasNotch;}/*** HUAWEI* com.huawei.android.util.HwNotchSizeUtil* public static boolean hasNotchInScreen()** @param context Context* @return hasNotch*/public static boolean hasNotchInHuawei(Context context){boolean hasNotch = false;try {ClassLoader cl = context.getClassLoader();Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");hasNotch = (boolean) get.invoke(HwNotchSizeUtil);} catch (Exception e) {e.printStackTrace();}return hasNotch;}public static boolean hasNotchInSmart(Context context){boolean hasNotch = false;try{Class<?> DisplayUtilsSmt = Class.forName("smartisanos.api.DisplayUtilsSmt");Method isFeatureSupport = DisplayUtilsSmt.getMethod("isFeatureSupport", int.class);hasNotch = (boolean) isFeatureSupport.invoke(DisplayUtilsSmt, 0x00000001);return hasNotch;}catch (Exception e){e.printStackTrace();}return hasNotch;}
安卓p以上的话,谷歌提供了接口去获取是否支持切口屏幕,并且返回切口的位置大小
protected static boolean isNotchEnable(Activity activity){DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();if(displayCutout == null || displayCutout.getBoundingRects() == null || displayCutout.getBoundingRects().size() == 0){return false;}return true;}@TargetApi(Build.VERSION_CODES.P)protected static int[] getNotchInfo(Activity activity){int[] notchSize = new int[]{0,0};DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();List<Rect> boundingRects = displayCutout.getBoundingRects();if(boundingRects.size() != 0){Rect rect = boundingRects.get(0);notchSize[0] = rect.width();notchSize[1] = rect.height();}return notchSize;}
这些其实网上有很多教程已经说过了,说一下我遇到的问题吧,
首先是,unity需要勾选安全区域外渲染
不然还是会有缺口,然后,安卓xml里面需要设置
max_aspect 代表屏幕比例哈,2400/1080 = 2.222;
在适配vivo时遇到个问题,他默认不打开刘海区域,需要在mainactivity 的oncreate加入全面屏
@see #LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 允许内容去延伸进刘海区
private static void SetWindowLayoutInDisplayCutoutMode(Activity act){WindowManager.LayoutParams lp = act.getWindow().getAttributes();lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;act.getWindow().setAttributes(lp);}
一般刘海适配的方案,在游戏里面就是吧ui缩放,位移,这里面有个回答不错
如何使用unity的ugui适配iPhoneX的齐刘海屏幕? - 知乎
他采取的策略是锚点向中靠拢.
我们游戏是横屏的,我做的是检查屏幕选择,然后挖孔的一方位移.主要使用ScreenOrientation.LandscapeLeft
和Screen.orientation类
if self._isleftOrientation ~= Screen.orientation thenself:RefreshUIWithNotch()self._isleftOrientation = Screen.orientationend
关于锚点还是锚边,不同的策略
AnchorMin和AnchorMax相等的话,就是锚点,直接AnchorPos.x - notchSizeX就行了
如果是stretch的,会随屏幕改变大小,anchorPos.x =AnchorPos.x + notchSizeX * (1 - beginPivot.x)
大概就是这样吧
好家伙,iphone已经不满足张雨绮屏幕了,开始水滴屏了,iPhone我们的策略是iPhone 平台直接写死大小,ios平台rawset(self, "_notchSize", Vector2(70, 200))