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 采用无边框设计。