一说到 Android 16 的适配,我今年被问得最多的一句话就是:“为什么我明明把状态栏和导航栏透明了,界面反而乱套了?”其实问题的根源不是“透明”本身,而是从 Android 15 开始,系统强制要求应用以 edge-to-edge(真正的内容全屏)方式绘制,Android 16 延续并强化了这套规则。这意味着旧时代那套“setStatusBarColor + fitsSystemWindows 碰运气”的写法已经彻底行不通了。
这篇文章不打算铺开讲 Android 16 新增了多少功能特性,而是围绕“系统内容全屏、状态栏透明、导航栏透明”这一组具体需求,把背后强制规则的来龙去脉、正确适配思路、以及容易踩的坑全部展开。无论你是正在做 targetSdk 升级,还是新项目刚起步,都可以把这份内容当作一张可直接照着做的路线图。
1. 为什么 Android 16 开始,全屏透明不再是选择题
1.1 从一个真实反馈说起:状态栏透明了,但界面也乱了
前两周一位朋友发来一张截图,界面上方文字卡在半透明黑色区域下面,底部又被白色导航条遮住一截。他的代码里还在用 API 30 时代的方法:给根布局设置 fitsSystemWindows=true,又手动调了 Window.setStatusBarColor(Color.TRANSPARENT),配合 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。结果旧设备上一切正常,新的 Android 16 测试机上全乱。
他问我的第一句话是:“是不是 Android 16 把状态栏适配接口改了?”
其实不是接口改了,而是接口的默认行为改了。旧代码在过去之所以能跑通,是因为系统一直允许开发者自己决定“要不要让内容延伸到系统栏后面”。从 Android 15 开始,系统直接把这个选择权收走了。Android 16 并不是第一个强制 edge-to-edge 的版本,但它把很多边界情况补齐了,导致以前半适配、碰巧能用的项目一下子现出原形。
1.2 Android 15 到 16 的政策变化:edge-to-edge 全面强制
先理清时间线。
Android 10 引入了官方深色模式,也完善了 WindowInsets 这套 API,当时系统栏透明已经可以做到很干净。但 Google 没有强制,开发者想用旧 API 也还能凑合。到了 Android 15(API 35),凡是 targetSdk >= 35 的应用,默认就是 edge-to-edge,系统不再给“退出全屏模式”的开关,setStatusBarColor 这类调用直接不生效,SYSTEM_UI_FLAG_* 系列标记也被忽略。
Android 16(API 36)延续了这条路线,并且把非全屏应用的一些限制做得更细。我个人的理解是,Google 希望从 Android 15 开始把所有 App 统一拉到同一条起跑线:内容默认延伸到系统栏后面,大家都要学会正确处理 Insets,而不是靠各写各的黑色状态栏、彩色导航栏去拼视觉效果。
这个变化对用户其实是好事。现在很多设备用挖孔屏、刘海屏、手势导航,如果应用不把内容全屏,屏幕利用率会很低,尤其横屏看视频或打游戏时,上下两条黑带特别浪费。但从开发者角度看,代价就是必须重新审视每一页的布局。
1.3 老一套 API 为什么靠不住
很多人在升级后困惑的是:我明明还在调用 statusBarColor,代码也没报错,为什么界面没有按预期渲染?
原因是 API 没有被删除,但系统在 targetSdk >= 35 时会用新的窗口策略覆盖你的设置。你可以继续调用,只是结果无效。类似的还有 View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,它从 API 30 起就被标记废弃,到 Android 15 之后基本等同摆设。如果你还在用 window.decorView.systemUiVisibility 手动拼二进制标志位,那几乎可以断定新的测试机型上会出现各种“时好时坏”的诡异问题。
我见过一套快速适配方案,是在测试机出问题后给所有页面补了 WindowCompat.setDecorFitsSystemWindows(window, false),然后发现状态栏确实透明了,但顶部 Toolbar 也顶到了摄像头挖孔里面。原因很简单:只把窗口设置为“不自动适配系统栏”,却没有给内容加上安全区 padding。真正合理的做法是理解并处理 WindowInsets,而不是单纯切换两个布尔开关。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 一步到位的全屏透明适配实践
2.1 第一步:用 enableEdgeToEdge 替代废弃的 StatusBarColor
从较新的 androidx.activity 版本开始,官方提供了一个非常顺手的入口:enableEdgeToEdge()。它可以直接在 Activity.onCreate 中调用,会自动完成三件事:把状态栏和导航栏设为透明、让内容延伸到系统栏后面、根据系统深浅色自动设置状态栏图标的明暗。
kotlin复制override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
}
这里有个细节很多人不知道:enableEdgeToEdge() 内部会调用 WindowCompat.setDecorFitsSystemWindows(window, false),还会处理导航栏对比度、系统图标可见性等。所以不要在调用它之后再手工去设置 systemUiVisibility 或 statusBarColor,两者会打架,而且手工代码往往是旧逻辑,容易把透明状态栏重新变成黑条或白条。
如果项目里有多个 BaseActivity,建议把 enableEdgeToEdge() 统一放
