unity 刘海全面屏适配

从2017年iPhoneX面世,到今天为止,当前主流的手机基本上都已经是刘海屏或打孔屏,更大的屏占比带来更好的视觉体验,因此对游戏而言,适配全面屏是必不可少的。

1:打开全面屏开关

Android:默认全面屏是关闭的

在AndroidManifest.xml中添加meta-data属性

<meta-data android:name="android.max_aspect" android:value="2.4" />

<meta-data android:name="android.notch_support" android:value="true"/>

<meta-data android:name="notch.config" android:value="portrait|landscape"/>

开启全面屏

备注:

不知道AndroidManifest.xml文件的可以从Unity编辑器的安装目录

“Editor\Data\PlaybackEngines\AndroidPlayer\Apk”

拷贝一份到工程的“Assets\Plugins\Android下”在此基础上修改

iOS: 默认全面屏是开启的

2:适配UI

2.1:获取刘海尺寸

我们只需要的到两个信息:1:是否是刘海屏 2:刘海的高度

Android:

1:AndroidP也就是Android9及以上版本,Google统一支持了全面屏的API

public class NotchAndroidP extends NotchBase {

    public NotchAndroidP(Context context)
    {
        super(context);
    }

    protected void Init()
    {
        getNotchInfo();
    }

    @TargetApi(28)
    protected void getNotchInfo() {
        final View decorView = ((Activity)_context).getWindow().getDecorView();
        decorView.post(new Runnable() {
            @Override
            public void run() {
                DisplayCutout displayCutout = decorView.getRootWindowInsets().getDisplayCutout();
                if (displayCutout != null)
                {
                    _hasNotch = true;
                    _notchHeight = displayCutout.getSafeInsetTop();
                }
                _isInit = true;
            }
        });
    }

    @TargetApi(28)
    public  void DisplayFullScreen()
    {
        Window window = ((Activity)_context).getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        window.setAttributes(lp);
    }

}

 

2:AndroidP以下每个手机厂商都定义了自己的API,来获取刘海信息

需要判断手机厂商然后根据类型分别处理:

    private static NotchType getNotchType()
    {
        int OSVersion = Build.VERSION.SDK_INT;
        if (OSVersion >= 28)
        {
            return NotchType.AndroidP;
        }
        String manufacturer = Build.MANUFACTURER.toUpperCase();
        Log.i("Notch", "phoneUpperModel:" + manufacturer);
        if (manufacturer.contains("HUAWEI")) {
            return NotchType.HuaWei;
        }
        if (manufacturer.contains("XIAOMI")) {
            return  NotchType.XiaoMi;
        }
        if (manufacturer.contains("OPPO")) {
            return  NotchType.OPPO;
        }
        if (manufacturer.contains("VIVO")){
            return NotchType.VIVO;
        }
        return NotchType.NONE;
    }

华为:

public class NotchHuaWei extends NotchBase {

    public NotchHuaWei(Context context)
    {
        super(context);
    }

    protected void Init()
    {
        try {
            ClassLoader cl = _context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method method = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            _hasNotch = (boolean) method.invoke(HwNotchSizeUtil);
            if (_hasNotch)
            {
                method = HwNotchSizeUtil.getMethod("getNotchSize");
                int[] size = (int[]) method.invoke(HwNotchSizeUtil);
                if (size != null && size.length == 2)
                {
                    _notchHeight = size[1];
                }
            }
        }
        catch (Exception e) {
            Log.e("Notch", e.toString());
        }
        _isInit = true;
    }
}

小米:

public class NotchXiaoMi extends NotchBase {

    public NotchXiaoMi(Context context)
    {
        super(context);
    }

    protected void Init()
    {
        try {
            ClassLoader cl = _context.getClassLoader();
            Class SystemProperties = cl.loadClass("android.os.SystemProperties");
            Method method = SystemProperties.getMethod("get", String.class);
            String strNotch = (String)(method.invoke(SystemProperties, "ro.miui.notch"));
            _hasNotch = strNotch.compareTo("1") == 0;
            if (_hasNotch)
            {
                int resourceId = _context.getResources().getIdentifier("notch_height", "dimen", "android");
                if (resourceId > 0) {
                    _notchHeight = _context.getResources().getDimensionPixelSize(resourceId);
                }
            }
        } catch (Exception e) {
            Log.e("Notch", e.toString());
        }
        _isInit = true;
    }
}

官方文档:文档中心

OPPO:

public class NotchOppo extends NotchBase {

    public NotchOppo(Context context)
    {
        super(context);
    }

    protected void Init()
    {
        PackageManager pm = _context.getPackageManager();
        _hasNotch = pm.hasSystemFeature("com.oppo.feature.screen.heteromorphism");
        if (_hasNotch)
        {
            _notchHeight = 80;
        }
        _isInit = true;
    }
}

官方文档:OPPO开放平台

VIVO:

public class NotchVivo extends NotchBase {

    public static final int VIVO_NOTCH = 0x00000020;    //是否有刘海
    public static final int VIVO_FILLET = 0x00000008;   //是否有圆角

    public NotchVivo(Context context)
    {
        super(context);
    }

    protected void Init()
    {
        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);
            if (_hasNotch)
            {
                _notchHeight = 32;
            }
        } catch (Exception e) {
            Log.e("Notch", e.toString());
        }
        _isInit = true;
    }
}

官方文档:https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf

整个Java代码打包成jar导出给Unity使用

    private IEnumerator InitNotchAndroid()
    {
        AndroidJavaClass notchUtilsClass = new AndroidJavaClass("com.utils.notch.NotchUtils");
        if(notchUtilsClass != null)
        {
            AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
            notchUtilsClass.CallStatic("init", new object[] { currentActivity });
            bool isInitDone = false;
            while(!isInitDone)
            {
                isInitDone = notchUtilsClass.CallStatic<bool>("isInitDone");
                yield return null;
            }
            _hasNotch = notchUtilsClass.CallStatic<bool>("hasNotch");
            if(_hasNotch)
            {
                _notchSize = notchUtilsClass.CallStatic<int>("getNotchHeight");
            }
        }
        yield return null;
    }

iOS:

采用Unity自带的函数 Screen.safeArea,在横屏下其中的X值就代表刘海的高度,Unity版本使用的是2017

    private IEnumerator InitNotchiOS()
    {
        float notchSize = Screen.safeArea.x;
        if (notchSize > 0.0f)
        {
            _hasNotch = true;
            _notchSize = notchSize;
        }
        yield return null;
    }

2.2 设置UI偏移

这里采用UGUI来实现UI,以下都以横屏游戏为例

在UGUI中通过Anchor来设置RectTransform的矩形范围

anchorMin:设置xmin,ymin,相对父节点的百分比

anchorMax:设置xmax,ymax,相对父节点的百分比

例如:

anchorMin:(0,0)

anchorMax:(1,1)

这代表与父节点大小一样大

我们一般在Canvas节点下建立一个空的RectTransform节点,设置其Anchor,使其与父节点一样大,也就是屏幕的大小

获取刘海的高度后,除以屏幕的宽度得到百分比,然后设置anchorMin.x

anchorMin.x = 刘海的高度 / Screen.width

整个UI的矩形范围左侧就会缩进

在iPhone11模拟器上测试:

 

转载自:https://zhuanlan.zhihu.com/p/126699544

发布于 2020-04-09

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值