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;
    }
相关推荐
驰骋工作流5 小时前
流程时效考核的表结构:从待办时限到 WF_CH 考核结果驰骋BPM驰骋低代码低代码工作流引擎
android·低代码·rxjava
传奇开心果编程7 小时前
【Flutter踩坑排雷】第7课:巨型 build 函数坑|全部 UI 写在同一个 build,维护难、隐性异常
android·flutter·ios·移动开发·跨平台·dart·声明式ui
方白羽10 小时前
Android 双开环境底层剖析与风控检测落地
android·安全·app
weixin_5633714711 小时前
Android Studio 2024 版 Device Explorer 打开方法
android·ide·android studio
AIsoft_868913 小时前
职场音频文件怎么整理?录音APP有哪些用法
android·音视频
booboosui13 小时前
第一批个人 Agent 用户正在卸载,问题不在模型,在它住在哪儿
android
洞见前行14 小时前
点击图标到内容出现,你的 App 在这几秒里做了什么:Android 冷启动全链路优化实战
android·性能优化·android studio
凯基迪科技14 小时前
芯片UID绑定修改 加密与逆向修改思路分析
android
Liben15 小时前
Weex开发踩坑记录
android·前端·ios
PiaoKe___15 小时前
云手机技术解析:从 ARM 虚拟化到 Python 自动化实战
python·智能手机·自动化