应对 Android 15 强制执行的无边框措施

3. 让应用采用 Android 15 中的无边框设计

什么是无边框?

应用可以在系统栏的后方进行绘制,从而提供优质的用户体验并充分利用显示空间。这就是所谓的“无边框”。

如何应对 Android 15 无边框变更

在 Android 15 之前,应用的界面默认情况下只能避开系统栏区域(例如状态栏和导航栏)进行布局。应用可以选择采用无边框设计;但根据应用的不同,选择采用该设计的难易程度也各不相同。

从 Android 15 开始,应用将默认采用无边框设计。您将看到以下默认设置:

三按钮导航栏是半透明的。

手势导航栏是透明的。

状态栏是透明的。

除非内容应用了边衬区或内边距,否则内容将绘制在系统栏(例如导航栏、状态栏和标题栏)后面。

这样可确保无边框设计作为提高应用质量的一种手段不会被忽视,并减少对应用采用无边框设计所需的工作量。不过,这项变更可能会对应用产生负面影响。我们稍后会举例说明将目标 SDK 升级到 Android 15 后,对 SociaLite 造成的两个负面影响。

将目标 SDK 值更改为 Android 15

在 SociaLite 应用的 build.gradle 文件中,将目标 SDK 版本和编译 SDK 版本更改为 Android 15 或 VanillaIceCream。

如果您是在 Android 15 稳定版发布之前学习此 Codelab,代码将如下所示:

android {

namespace = "com.google.android.samples.socialite"

compileSdkPreview = "VanillaIceCream"

defaultConfig {

applicationId = "com.google.android.samples.socialite"

minSdk = 21

targetSdkPreview = "VanillaIceCream"

...

}

...

}

如果您是在 Android 15 稳定版发布之后学习此 Codelab,代码将如下所示:

android {

namespace = "com.google.android.samples.socialite"

compileSdk = 35

defaultConfig {

applicationId = "com.google.android.samples.socialite"

minSdk = 21

targetSdk = 35

...

}

...

}

重新构建 SociaLite 并观察以下问题:

三按钮导航背景保护与导航栏不匹配。对于手势导航,您无需执行任何操作,Chats 屏幕即会实现无边框设计。不过,仍然存在三按钮导航背景保护,应予以移除。

采用三按钮导航的 Chats 屏幕

采用手势导航的 Chats 屏幕

界面被遮挡。对话的底部界面元素被导航栏遮挡。这种情况在三按钮导航中最为明显。

谈论狗狗的聊天消息(三按钮导航)

谈论狗狗的聊天消息(手势导航)

修正 SociaLite

如需移除默认的三按钮导航背景保护,请按以下步骤操作:

在 MainActivity.kt 文件中,将 window.isNavigationBarContrastEnforced 属性设为 false,即可移除默认的背景保护。

class MainActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

installSplashScreen()

super.onCreate(savedInstanceState)

setContent {

// Add this block:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

window.isNavigationBarContrastEnforced = false

}

}

}

...

}

window.isNavigationBarContrastEnforced 可确保在请求完全透明的背景时,导航栏具有足够的对比度。通过将此属性设置为 false,您可以有效地将三按钮导航背景设置为透明。window.isNavigationBarContrastEnforced 只会影响三按钮导航,不会影响手势导航。

重新运行该应用,并在 Android 15 设备上查看其中一个对话。Timeline、Chats 和 Settings 屏幕现在都会显示为无边框。应用的 NavigationBar(包含 Timeline、Chats 和 Settings 按钮)会在系统的透明三按钮导航栏后方绘制。

移除了条带的 Chats 屏幕

手势导航没有任何变化

但请注意,对话的 InputBar 仍被系统栏遮挡。您需要正确处理边衬区,才能解决此问题。

谈论狗狗的对话(三按钮导航)。底部的输入字段被系统的导航栏遮挡。

谈论狗狗的对话(手势导航)。底部的输入字段被系统的导航栏遮挡。

在 SociaLite 中,InputBar 会被遮挡。在实际操作中,当您旋转到横屏模式或使用大屏设备时,可能会发现顶部、底部、左侧和右侧的元素被遮挡。因此,请针对所有这些用例,考虑如何处理边衬区。对于 SociaLite,您可以应用内边距来抬高 InputBar 的可点按内容。

如需应用边衬区来解决界面被遮挡的问题,请按以下步骤操作:

打开 ui/chat/ChatScreen.kt 文件,在第 178 行附近找到 ChatContent 可组合函数,其中包含对话屏幕的界面。ChatContent 可利用 Scaffold 轻松构建界面。默认情况下,Scaffold 会以边衬区的形式提供关于系统界面的信息(例如系统栏的深度),您可以通过 Scaffold 的内边距值(innerPadding 参数)来使用这些信息。使用 Scaffold 的 innerPadding 向 InputBar 添加内边距。

在 ChatContent 中找到 InputBar(位于第 214 行附近)。这是一个自定义的可组合函数,用于创建供用户编写消息的界面。预览如下所示:

InputBar 获取了 contentPadding,并将其作为内边距应用到包含界面其余部分的 Row 可组合函数中。该内边距将应用于 Row 可组合函数的所有边。您可以在第 432 行附近看到这一点。以下是 InputBar 可组合函数,以供参考(请勿添加此代码):

// Don't add this code because it's only for reference.

@Composable

private fun InputBar(

contentPadding: PaddingValues,

...,

) {

Surface(...) {

Row(

modifier = Modifier

.padding(contentPadding)

...

) {

IconButton(...) { ... } // take picture

IconButton(...) { ... } // attach picture

TextField(...) // write message

FilledIconButton(...){ ... } // send message

}

}

}

}

返回到 ChatContent 中的 InputBar 并更改 contentPadding,以便使用系统栏边衬区。大约是在第 220 行附近。

InputBar(

...

contentPadding = innerPadding, //Add this line.

// contentPadding = PaddingValues(0.dp), // Remove this line.

...

)

在 Android 15 设备上重新运行该应用。

谈论狗狗的对话(三按钮导航),其中错误地应用了边衬区。

谈论狗狗的对话(手势导航),其中错误地应用了边衬区。

应用了底部内边距,按钮不会再被系统栏遮挡;但同时也应用了顶部内边距。顶部内边距包含 TopAppBar 和系统栏的深度。Scaffold 会将内边距值传递给它的内容,这样就可以同时避开顶部应用栏和系统栏。

如需修正顶部内边距,可创建 innerPadding PaddingValues 的副本,将顶部内边距设置为 0.dp,然后将修改后的副本传入 contentPadding。

InputBar(

...

contentPadding = innerPadding.copy(layoutDirection, top = 0.dp), //Add this line.

// contentPadding = innerPadding, // Remove this line.

...

)

注意:layoutDirection 在几行代码前已被定义为 LocalLayoutDirection.current。这样,您就可以考虑从左到右或从右到左布局的可组合函数,这在本地化为其他语言时非常有用。

注意:copy 是 SociaLite 独有的方法。您可以在第 230 行附近查看该方法。在您的应用中,您可以创建类似的函数,或者选择以其他方式处理边衬区。这里的要点是,以适合您应用的方式处理边衬区。

在 Android 15 设备上重新运行该应用。

谈论狗狗的对话(三按钮导航),已正确应用边衬区。

谈论狗狗的对话(手势导航),已正确应用边衬区。

恭喜!您已让 SociaLite 兼容了 Android 15 无边框平台变更。接下来,您将学习如何以向后兼容的方式使 SociaLite 采用无边框设计。