沉浸模式 | 手势导航连载 (四)
作者 / Chris Banes, Android 开发者关系团队工程师
什么是沉浸模式?
沉浸模式是一种让内容全屏呈现的方式,用来隐藏系统栏,从而确保应用拥有最大的屏幕空间。此外,它还提供了防误操作的功能 (比如意外使用手势离开应用),特别适合在游戏中采用。
非粘性沉浸模式: 用户可以通过在系统栏上滑动来退出沉浸模式。
粘性沉浸模式: 用户可以通过在系统栏上滑动来暂时退出沉浸模式。在经过一小段时间后 (只有几秒) 会重新自动回到沉浸模式。
系统栏隐藏: 在此状态下,返回主屏幕手势和后退手势均被禁用。用户必须首先从边缘向内侧滑动才能让系统栏显示。
系统栏显示: 在此状态下,返回主屏幕手势和后退手势可以正常工作。
现在,我们已经了解了沉浸模式的基础知识,下面介绍这两种不同模式的细节。
非粘性沉浸模式
大家在上面的流程图中可能已经看到,非粘性 (non-sticky) 沉浸模式非常适合需要全屏显示但不需要在屏幕边缘附近使用精确滑动手势的 UI。常见的例子包括全屏视频播放和照片浏览等。
就手势导航而言,非粘性沉浸模式与其在早期版本的 Android 上的工作方式一致。在 Android 10 或以上系统中运行时,应用可以使用我们在上一篇文章中介绍的手势区域排除 API 。在此模式下,无论系统栏是否可见,每个边缘能排除的区域高度仍旧限制为 200dp。
如果您的应用正在使用非粘性沉浸模式,我们建议您回顾一下第三篇文章,避免在屏幕边缘出现的视图与系统手势出现冲突。
粘性沉浸模式
可以看到,用户现在可以在屏幕边缘附近自由绘制,后退手势不会再干扰他们。如果用户想要退出应用,则可以从屏幕底部向上滑动呼出系统栏,进行后退或返回主屏的操作。
在实现方面,此处使用的代码大体沿用自第三篇文章中的 "使用手势区域排除 API" 部分,不同之处在于,我们希望视图能够知道它自身是否处于沉浸模式之中:
private val exclusionRects = ArrayList<Rect>()
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed && Build.VERSION.SDK_INT >= 29) {
updateGestureExclusionRects()
}
}
override fun onWindowSystemUiVisibilityChanged(visibility: Int) {
super.onWindowSystemUiVisibilityChanged(visibility)
// Update our gesture exclusions rects if we’re
// running on Android 10+
if (Build.VERSION.SDK_INT >= 29) {
updateGestureExclusionRects()
}
}
private fun updateGestureExclusionRects() {
// If the navigation bar is hidden, let's exclude any vertical edges so
// that the user can draw freely
if ((windowSystemUiVisibility and SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
// Root window insets are null, which happens if this is called
// before we're attached and laid out. Ignore the call for now.
val rootWindowInsets = rootWindowInsets ?: return
val gestureInsets = rootWindowInsets.systemGestureInsets
exclusionRects.clear()
// Add an exclusion rect for the left gesture edge
exclusionRects += Rect(0, 0, gestureInsets.left, height)
// Add an exclusion rect for the right gesture edge
exclusionRects += Rect(width - gestureInsets.right, 0, width, height)
systemGestureExclusionRects = exclusionRects
} else {
// If the navigation bar is showing, we don't want to exclude any edges.
systemGestureExclusionRects = emptyList()
}
}
您可以在 GitHub 上阅读 Makers 应用更新的完整代码。
在 Android 10 上使用手势区域排除 API https://github.com/chrisbanes/markers/commit/5e7dcb5ec93dae0ac30ed42b6558da2e86af26bf
总结对比: 非粘性与粘性
继续深入
想了解更多 Android 内容?
在公众号首页发送关键词 "Android",获取相关历史技术文章;
在公众号首页发送关键词 "ADS",获取开发者峰会演讲中文字幕视频;
还有更多疑惑?欢迎点击菜单 "联系我们" 反馈您在开发过程中遇到的问题。
推荐阅读