Unity适配 安卓15+三键导航模式下的 底部UI被遮挡

在发布android15以上的apk,如果手机采用的经典导航键,那么底部的按钮将会被安全区域遮挡。

解决这个问题,有两种思路。

1.打开全屏模式

cs 复制代码
private void FullScreen()
{
    // 强制设置全屏
    Screen.fullScreen = true;
    // 使用沉浸模式,隐藏底部的虚拟按键
    Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
}

全屏下,导航栏会默认消失,但是你从底部下往上滑动的时候,导航栏会出现,一会后会自动消失

2.获取安全区域的高度,让UI的位置+安全区域的高度

cs 复制代码
    private RectTransform rt;
    private Canvas canvas;

    private void ApplySafeOffset()
    {

        rt = GetComponent<RectTransform>();
        canvas = GetComponentInParent<Canvas>();
        if (rt == null || canvas == null) return;

        float bottomPixelHeight = 0;

        // 首先尝试原生接口 
        if (Application.platform == RuntimePlatform.Android)
        {
            bottomPixelHeight = GetAndroidBottomInset();
            if (bottomPixelHeight > 0)
                Debug.Log($"[SafeAreaAdapter] 从 Android 底层获取到避让高度: {bottomPixelHeight}");
        }
        else
            return;

     
        if (bottomPixelHeight > 0)
        {
            float scaleFactor = canvas.scaleFactor;
            float offsetInCanvas = bottomPixelHeight / scaleFactor;

            Vector2 newPos = rt.anchoredPosition;
            newPos.y = offsetInCanvas; // 直接设置为偏移量,避免重复累加
            rt.anchoredPosition = newPos;
            Debug.Log($"[SafeAreaAdapter] 适配成功: {offsetInCanvas} Canvas单位");
        }
        else
        {
            Debug.Log("[SafeAreaAdapter] 所有检测均返回0,可能是全屏手势模式。");
        }
    }

    // 调用 Android 原生 API 获取真正的底部高度
    private float GetAndroidBottomInset()
    {
        try
        {
            using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            using (var activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            using (var window = activity.Call<AndroidJavaObject>("getWindow"))
            using (var decorView = window.Call<AndroidJavaObject>("getDecorView"))
            using (var rootInsets = decorView.Call<AndroidJavaObject>("getRootWindowInsets"))
            {
                if (rootInsets != null)
                {
                    // 获取系统窗口插入高度 (包括导航栏)
                    return rootInsets.Call<int>("getSystemWindowInsetBottom");
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError("[SafeAreaAdapter] 获取原生 Insets 出错: " + e.Message);
        }
        return 0;
    }

这里增加一个判断,要大于35的才能去抬高,因为在android15之前,是不用抬起的,这里不加判断设置android版本的话,只要有安全区域就会抬起,是有问题

复制代码
    public int GetAndroidSDKVersion()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
    using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
    {
        // Android 15 对应的 SDK_INT 是 35
        return version.GetStatic<int>("SDK_INT");
    }
#endif
        return -1;
    }
相关推荐
Android研究员7 小时前
Android进阶之事件分发机制深度剖析
android·前端·面试
雅客李7 小时前
2026年第三季度云手机实测 游戏多开挂机托管三维度数据公开
游戏·智能手机
JoyCong19988 小时前
手机变身“司令台”!ToDesk AI安卓版上线
网络·人工智能·科技·智能手机·电脑·远程工作·远程操作
峥嵘life8 小时前
Android WiFi连接过程 wpa_supplicant 日志分析
android·开发语言·php
Android小码家9 小时前
OWASP 移动应用安全之授权(MASTG-DEMO-0090)
android·安全·frida
Summer-Bright9 小时前
消费者 AI 变现竞争:从“一家独大“到“iOS vs Android“,谁在为 AI 买单?
android·人工智能·ios·ai·自然语言处理·agi
Xzaveir10 小时前
企业号码资产平台:逐号状态、事件日志与批次聚合
android·人工智能
峥嵘life11 小时前
Android 系统应用蓝牙分享失败分析解决
android·gitee
恋猫de小郭11 小时前
Flutter 3D 渲染的全新选择和应用场景
android·前端·flutter
小二·11 小时前
七家手机厂商通过备案:苹果/华为/OPPO/vivo/小米/三星/努比亚端侧AI大模型技术深度解析
人工智能·华为·智能手机