在 Unity 中开发 Android 应用时,处理刘海屏(Notch)设备是一个需要注意的细节。刘海屏设备在屏幕顶部有一个凹口,用于放置摄像头、传感器等硬件组件。为了确保应用在这些设备上有良好的用户体验,需要正确处理刘海屏区域。
安卓刘海屏、水滴屏等在谷歌官方文档中统一命名为缺口屏(Notch Screen)。要获取Android手机刘海屏的信息,需要在JAVA层调用android的API。Google从Android P(API 28)开始提供了官方API,用于获取缺口屏信息。对于安装了Android P之前版本系统的手机,就没有Google官方API帮助我们了。不过,华为、小米、OPPO、VIVO、三星等手机厂商在自家定制系统中提供了自己的API,我们可以通过反射的方式调用这些API来获取缺口屏信息。
在Unity中实现Android缺口屏适配的思路是
1)获取当前手机是否为缺口平;
2)获取缺口屏缺口尺寸;
3)让游戏渲染进缺口区域;
4)位移游戏中的UI元素,防止刘海区域遮挡UI
下面将会详细讲解以原生和unity两种实现方式
原生
在 Unity 中使用 Android 底层 API 接口来实现缺口屏(刘海屏)适配,可以通过调用 Android 的原生代码来获取设备的缺口信息。以下是详细的实现步骤和代码示例:
1. 获取当前手机是否为缺口屏
通过调用 Android 的原生 API,可以获取设备是否为缺口屏。
2. 获取缺口屏缺口尺寸
通过 Android 的原生 API 获取缺口屏的缺口尺寸。
3. 让游戏渲染进缺口区域
确保游戏在全屏模式下运行,并且允许渲染到缺口区域。
4. 位移游戏中的 UI 元素,防止刘海区域遮挡 UI
使用 Screen.safeArea 动态调整 UI 元素的位置和大小,确保它们不会被刘海遮挡。
实现步骤和代码示例
1. 创建 Android 原生插件
首先,需要创建一个 Android 原生插件来获取缺口屏信息。
- 在 Unity 项目中创建一个
Plugins/Android文件夹。 - 在
Plugins/Android文件夹中创建一个新的 Android Studio 项目,或者直接创建一个 Java 文件。
以下是一个示例 Java 文件 NotchUtils.java:
package com.yourcompany.notchutils;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.view.DisplayCutout;
import android.view.WindowInsets;
public class NotchUtils {
public static boolean hasNotch(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets windowInsets = activity.getWindow().getDecorView().getRootWindowInsets();
if (windowInsets != null) {
DisplayCutout displayCutout = windowInsets.getDisplayCutout();
return displayCutout != null;
}
}
return false;
}
public static Rect getNotchSize(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets windowInsets = activity.getWindow().getDecorView().getRootWindowInsets();
if (windowInsets != null) {
DisplayCutout displayCutout = windowInsets.getDisplayCutout();
if (displayCutout != null) {
Rect safeInsetRect = new Rect(
displayCutout.getSafeInsetLeft(),
displayCutout.getSafeInsetTop(),
displayCutout.getSafeInsetRight(),
displayCutout.getSafeInsetBottom()
);
return safeInsetRect;
}
}
}
return new Rect(0, 0, 0, 0);
}
}
编译这个 Java 文件并生成 .jar 文件,然后将其放入 Plugins/Android 文件夹中。
2. 在 Unity 中调用 Android 原生插件
在 Unity 中编写一个 C# 脚本来调用 Android 原生插件。
using UnityEngine;
using System.Runtime.InteropServices;
public class NotchScreenHandler : MonoBehaviour
{
private AndroidJavaObject activity;
private AndroidJavaClass notchUtils;
void Start()
{
if (Application.platform == RuntimePlatform.Android)
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
}
notchUtils = new AndroidJavaClass("com.yourcompany.notchutils.NotchUtils");
bool hasNotch = notchUtils.CallStatic<bool>("hasNotch", activity);
if (hasNotch)
{
Rect notchSize = GetNotchSize();
Debug.Log("Notch Size: " + notchSize);
// Adjust UI elements based on notch size
AdjustUIForNotch(notchSize);
}
}
}
Rect GetNotchSize()
{
AndroidJavaObject rect = notchUtils.CallStatic<AndroidJavaObject>("getNotchSize", activity);
int left = rect.Get<int>("left");
int top = rect.Get<int>("top");
int right = rect.Get<int>("right");
int bottom = rect.Get<int>("bottom");
return new Rect(left, top, right - left, bottom - top);
}
void AdjustUIForNotch(Rect notchSize)
{
// Implement your UI adjustment logic here
// For example, move UI elements to avoid the notch area
}
}
3. 确保游戏渲染进缺口区域
在 Player Settings 中设置全屏模式:
- 打开
Edit > Project Settings > Player。 - 在
Resolution and Presentation部分,确保Fullscreen Mode设置为Fullscreen Window或Maximized Window。 - 确保
Render Outside Safe Area选项被勾选。
4. 位移游戏中的 UI 元素,防止刘海区域遮挡 UI
在 NotchScreenHandler 脚本中,编写逻辑来调整 UI 元素的位置和大小,确保它们不会被刘海遮挡。
using UnityEngine;
using UnityEngine.UI;
public class NotchScreenHandler : MonoBehaviour
{
private AndroidJavaObject activity;
private AndroidJavaClass notchUtils;
void Start()
{
if (Application.platform == RuntimePlatform.Android)
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
}
notchUtils = new AndroidJavaClass("com.yourcompany.notchutils.NotchUtils");
bool hasNotch = notchUtils.CallStatic<bool>("hasNotch", activity);
if (hasNotch)
{
Rect notchSize = GetNotchSize();
Debug.Log("Notch Size: " + notchSize);
AdjustUIForNotch(notchSize);
}
}
}
Rect GetNotchSize()
{
AndroidJavaObject rect = notchUtils.CallStatic<AndroidJavaObject>("getNotchSize", activity);
int left = rect.Get<int>("left");
int top = rect.Get<int>("top");
int right = rect.Get<int>("right");
int bottom = rect.Get<int>("bottom");
return new Rect(left, top, right - left, bottom - top);
}
void AdjustUIForNotch(Rect notchSize)
{
// 获取 Canvas 的 RectTransform
RectTransform canvasRectTransform = GetComponent<RectTransform>();
// 计算安全区域
Rect safeArea = Screen.safeArea;
// 将安全区域转换为 Canvas 的坐标
Vector2 anchorMin = safeArea.position;
Vector2 anchorMax = safeArea.position + safeArea.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
// 设置 Canvas 的锚点
canvasRectTransform.anchorMin = anchorMin;
canvasRectTransform.anchorMax = anchorMax;
// 你可以在这里进一步调整 UI 元素的位置和大小
// 例如,移动顶部的 UI 元素以避免被刘海遮挡
foreach (RectTransform child in canvasRectTransform)
{
if (child.anchorMin.y == 1 && child.anchorMax.y == 1)
{
// 这是一个顶部对齐的 UI 元素
child.anchoredPosition += new Vector2(0, -notchSize.height);
}
}
}
}
unity
在 Unity 中实现 Android 缺口屏(刘海屏)适配的思路可以按照你提到的步骤进行。以下是详细的实现步骤和代码示例:
1. 获取当前手机是否为缺口屏
在 Unity 中,无法直接通过 API 获取设备是否为缺口屏,但可以通过 Screen.safeArea 属性来判断屏幕的安全区域。如果安全区域小于屏幕的全区域,则可以认为设备有刘海。
2. 获取缺口屏缺口尺寸
通过 Screen.safeArea 可以获取屏幕的安全区域,从而计算出缺口的尺寸。
3. 让游戏渲染进缺口区域
确保游戏在全屏模式下运行,并且允许渲染到缺口区域。
4. 位移游戏中的 UI 元素,防止刘海区域遮挡 UI
使用 Screen.safeArea 动态调整 UI 元素的位置和大小,确保它们不会被刘海遮挡。
实现步骤和代码示例
1. 设置全屏模式
在 Player Settings 中设置全屏模式:
- 打开
Edit > Project Settings > Player。 - 在
Resolution and Presentation部分,勾选Fullscreen Mode。
2. 编写 SafeAreaHandler 脚本
编写一个脚本来处理安全区域,并调整 UI 元素的位置和大小。
using UnityEngine;
using UnityEngine.UI;
public class SafeAreaHandler : MonoBehaviour
{
private RectTransform rectTransform;
void Start()
{
rectTransform = GetComponent<RectTransform>();
ApplySafeArea();
}
void ApplySafeArea()
{
Rect safeArea = Screen.safeArea;
Vector2 anchorMin = safeArea.position;
Vector2 anchorMax = safeArea.position + safeArea.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
}
void Update()
{
// Optional: Continuously check and apply safe area in case of orientation changes
ApplySafeArea();
}
}
将此脚本附加到需要调整的 UI 元素上(如 Canvas 或 Panel)。
3. 确保游戏渲染进缺口区域
在 Player Settings 中,确保以下设置:
- 打开
Edit > Project Settings > Player。 - 在
Resolution and Presentation部分,确保Render Outside Safe Area选项被勾选。

1万+

被折叠的 条评论
为什么被折叠?



