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;
    }
相关推荐
终端安全笔记1 小时前
描述文件、企业证书、MDM 不是三个名字,是三层
android·ios·智能手机
字节暗面2 小时前
一次游戏安全SO静态分析记录:腾讯ACE与FairGuard加固强度对比
android·逆向工程·游戏加固
传奇开心果编程2 小时前
【Jetpack Compose基础语法学与练】第9课 SideEffect副作用 + LaunchedEffect,处理异步任务和生命周期
android·学习·ui·kotlin·android jetpack
2401_833269304 小时前
RecyclerView多布局详解
android
v_34836087624 小时前
Android_8 zygote启动分析
android
消失的旧时光-19435 小时前
Android 系统层扫盲 11:JNI 到底是什么?Java / Kotlin 是怎么调用 C/C++ 的?
android·binder·zygote·system_server·aops
mmsx5 小时前
Android 地图几万要素卡成幻灯片?顶点缓冲批上传与显存复用
android·opengl·地图·栅格
北京自在科技15 小时前
谷歌 Find Hub 迎来新版本更新
android·安卓
古法安卓21 小时前
Android-休眠唤醒后onLocationChanged没有数据问题排查
android·java·android studio
Htr_1 天前
Creem 2.0 使用指南:面向 AI 构建时代的资金平台
android·数据库·人工智能·ui·photoshop