Android Q Labs | Android Q 手势导航

接下来我将为你们介绍一个新的系统UI的功能:手势导航。同时想要利用这个机会和你们聊一聊做为开发者,应该如何去适配全面屏或者说新的全手势导航的模式。windows

手持设备的演化史

随着时间的发展,咱们能够看到手持设备的体积变得愈来愈小,屏幕自己则变得愈来愈大,而后屏幕在设备上的占有比例也变得愈来愈高。能够看到到最近年这些手持设备硬件上面的边框真的是变得愈来愈来越细小。同时,咱们也看到不少硬件厂商在这方面有更多的创新,例如说可折叠式的手机。安全

全面屏的趋势

1.用户对全面屏的需求

2.各设备厂商的创新

2.应用对不一样手势的支持

3.Android 系统的解决方案

这样一个全面屏的趋势,主要是因为用户对更大屏幕的需求。固然,这也离不开各个设备厂商在硬件方面各类各样的创新。ide

咱们也看到,这两年除了在硬件方面以外,不少的厂商在软件方面去考虑如何使用全手势的这种操做来给用户更多的屏幕空间。不一样的设备厂商提供了不一样的手势操做。布局

那么对于在座的开发者来讲,这虽然是一个好事情,但也可能意味着咱们的工做量变大了:由于咱们在研发过程当中要适配不一样的手势,可能要专门为一些设备的手势进行设计、研发、测试等等。post

那么,从安卓系统角度,咱们就想要去帮你们解决这个问题,因此在今年的 Android Q 咱们为你们推出了新的手势导航的功能。测试

Android Q 全新的手势导航

你可能仍是看到的是以前比较经典的三个按键的导航,那么你只要进入系统设置,里面有一个 gesture 选项,而后你就能够开启如今全新的手势导航了。 优化

对于尚未机会去尝试新手势的朋友,我这边有三张动图,基本上体现了新的手势导航用户是如何来操做的。

可能应用演练的第一大特色就是咱们原来底部的导航栏的黑色区域消失了,取而代之的是很是小的一个虚拟的导航按钮。

咱们先从最左边的来说,能够看到当用户从屏幕的底端,也就是如今虚拟的导航按键这里往上推的时候,用户能够退出当前应用,也就是说这个手势代替的是咱们以前的home按键,即退出当前应用。spa

中间这个手势代替的是“用户回到最已经浏览过的应用”手势,操做是从底部往上推,而后停留。设计

最右边是今年新增长的另一个手势,也就是返回的手势。他代替的是以前三个导航按键当中“返回”的按钮。3d

这张动图没有彻底包括新的手势。在 Beta3 中新的手势是支持同时向左侧滑动和向右侧滑动这两个手势的。能够看到,这张动图中咱们只包括了从左侧滑动。当用户在屏幕的边缘向左侧或者是向右侧滑动的时候,用户就能够回到上一个页面了。

说到这里可能你们会有一个疑问,由于在过去安卓系统上经典的三个按键的导航模式推出了不少年,大部分的用户也很习惯于使用这样的导航模式,那今年推出的新的全手势的导航,对于安卓微生态来讲意味着什么呢?

我要先解释、澄清一下:首先三个按键的导航模式咱们会继续沿用的

几个方面的缘由,很重要的一点就是不少的用户已经习惯于这样的导航模式,特别是针对于有无障碍需求的一些用户,对他来讲三个按键导航能够帮助他去使用设备,因此咱们会继续沿用三个按键的导航。同时,咱们会要求全部的安卓设备都继续支持三个按键的导航,用户就永远有一个能够返回去的备选方案。

在这个基础上有今年咱们推出的全手势导航,具体的手势内容就是主要的那三种手势,也就是刚刚你们看到动图。接下来咱们会继续和各个厂商努力把手势导航的这几个操做统一化,以便帮助开发者去处理一个统一的手势导航。那么到这里 Android Q 中新的手势导航功能自己我就介绍到这里。

如何面对全面屏趋势?

接下来我想要跟你们聊一聊,做为开发者如何去面对如今全面屏的趋势,或者说新的手势导航,给你们几点建议。

1.建议你们利用全面屏

既然咱们有了更大的屏幕,做为开发者,咱们但愿你们去用这样一个更大的屏幕。当咱们把原来的布局放在新的全面屏的时候,可能就会遇到一些跟系统UI有冲突的地方。

2.利用 insets 调整布局

这个时候,咱们建议你们利用 insets 这个类来调整你的布局。

3.利用手势操做带来的冲突

若是说你的应用内部有一些功能,或者说有一些手势刚好是和系统的新手势重合或者冲突(大部分的状况下应该不会有这样的冲突发生,我以后会给你们一个例子),若是有这样的状况,你们务必要把这些问题解决一下。

什么是全面屏

说了这么久的全面屏,全面屏到底指的是什么?

这张图片基本上指的是过去这么长时间,通常应用能够利用的在屏幕上的一个所谓的“安全范围”。在 Android Q 上,咱们 首先建议你们去考虑使用最下面的导航栏区域。

导航栏不光包括我给你们展现的新的手势导航,同时也包括了三个按钮的经典式的导航,一样会推荐你们去使用导航栏的区域,以后会给你们介绍可使用这个区域的 API,这个 API 是在旧的安卓版本上一样兼容的,因此建议你们在适配 Q 的时候也能够考虑是否在以前的版本上一样加入这样的支持。

另外一方面,若是你的应用像这样:

你有一张图片或者是能够被用户滑动的内容,是能够利用到咱们最上面的状态栏的。

那么在 Android Q 当中咱们也建议你们去使用这样的状态栏,目的很简单:给用户全面屏的感觉,沉浸式的感觉。

一样,咱们也建议你们在适配 Q 的时候考虑是否在以前的版本上一样加入这样的支持。那么咱们就能够看到,咱们如今应用所用的屏幕的范围,从以前的范围变成了如图这样一个全面屏的范围。

代码实现

那么咱们具体应该怎样来实现?基本上也是三个部分:

你的应用须要告诉系统,你要在全面屏上布置显示的应用内容,在全面屏上显示的时候可能会出现一些问题。

例如说咱们这里看到应用内容的最下面的部分,若是没有作任何优化的话,系统的导航栏可能就会盖住应用的内容。这个时候,做为开发者就须要对导航栏进行一些优化。 或者是个人应用内部有一些 view 或者是像上图中的 floatingActionButton (悬浮按钮)。若是说你原来开发的时候它的位置是写死的,那么当你在全面屏布置的时候,可能就会有一些跟系统 UI 的冲突,而后用户就没有办法去继续使用你以前的一些功能了。

那么咱们来看第一部分,在全面屏上显示。

你们须要使用一个 API(不是新的API):setSystemUiVisibility。 这个 API 的名字很很清晰易懂,你能够用它来设置系统 UI 的可见度或是显示程度。那么当你使用那么当你在使用这个方法的时候,你要传入一些值,这些值告诉了系统如何去显示系统的 UI,或者说如何去显示个人应用的 UI。

setSystemUiVisibility

我把这些参数大部分列在了这里,这不是全部的参数。

经过传这个参数更改的是系统 UI 的可见度,也就是这个这个方法自己它的做用。

举几个例子:最上面 SYSTEM_UL_FLAG_LOW_PROGFILE,就是要让系统的 UI 呈现于一个 low profile 的状态,也就是一个低调的状态,不要影响到个人应用内容,那么接下来,若是我传入的是 SYSTEM_UL_FLAG_NAVIGATION,其实我就是告诉了系统,我要把导航栏隐藏起来。因此第一个部分是要告诉系统 UI 如何显示。

中间这部分的参数是特别适用于一个视频或者是游戏的界面想要给用户一种沉浸式的体验,那么就能够传入 SYSTEM_UL_FLAG_IMMERSIVE 这两个的参数,当用户须要看到这个系统 UI 按钮的时候,经过点击屏幕等等能够再让这个系统 UI 出现。

今天我要说的实际上是最下面的这三个参数,经过使用这三个参数你就可让你的应用在全面屏上显示。咱们具体来看一下这三个参数:

首先这里有一个 view ,我对 view 又设置了这个 view 呈现时候的系统 UI 的可见度,那么我传入的第一个参数就是 SYSTEM_UL_FLAG_LAYOUT_HIDE_NAVIGATION,它主要指的就是我要把个人应用 layout 在屏幕上,当系统的 navigation,也就是导航栏消失的时候,我告诉了系统我要利用导航栏的区域来显示个人应用内容,那么下面这个参数是大部分时间我建议你们使用的,传入 SYSTEM_UL_FLAG_LAYOUT_STABLE,它指的是不管这个屏幕是怎样布局内容,它的布局比例和内容都不会发生变化,因此是呈现一个 stable 的状态的。

那么,针对于状态栏,若是你须要使用的话,你就要传入这样一个参数:STSTEM_UL_FLAG_LAYOUT_FULLSCREEN,这个时候就是告诉了系统,我要在全屏显示包括状态栏。

咱们按照刚才的给出的建议,我有一个示例应用
能够看到我这个应用当中有一个底部应用内部的导航,那么我如今想要个人应用在全面屏上显示(在这里我只显示了应用的下半部分,可是对于状态栏实际上是同样的),咱们首先要告诉系统,我要在全屏显示,因此我在 view 上就设置了系统 UI 的可见度,传入了 stable 和 hide navigation 这两个参数。接着我就发现了一个问题:系统的 UI 栏盖住了个人内容
因此我须要告诉系统,我要把系统的导航栏设置为透明色,这个时候就能够在的 style 主题 theme 里面把 navigationBarColor 设置成 transparent,这样你的内容就能够全屏显示,而且让系统的导航栏处于一个透明的状态。

这个参数属性是咱们在 loli pop 以后就已经推出的,而且建议你们在适配或者是针对于 Android 9.0或9.0之前的设备都应用把导航栏设置为透明的这样的一行代码。

为何说是 Android9.0或者是9.0之前?由于在 Q 上咱们推荐你们去利用全面屏,因此系统也要想要帮助你们少作一些事情,因此当你在 Android Q 上使用全面屏的时候,系统的导航栏会帮助你自动从新给导航栏着色,并且是动态变化的。稍微想要提一下的是,对于大部分的设备咱们都有这样一个优化,可是对于某一些机型可能没有办法作到这样子的优化,对于那种状况,咱们会给他一个 static 的一个颜色。可是在 Android Q 以前咱们就没有办法帮你们,因此建议你们在 Android Q 以前,当你要使用导航栏的时候,你须要写这样一个代码,告诉系统说我要把导航栏设置为 transparent 透明色。

按照刚才的这两个例子,我先是把个人应用在全屏上显示,同时把导航栏设置为透明,而后就获得了这样的结果,但显然这不是咱们想要的,应用内部的导航和系统的导航彻底重合了,并且应用内部的导航是我要点击的操做,和系统的点击操做是彻底冲突的。这个时候,若是有些处理过全屏幕或者是在全屏幕展示本身应用的朋友,可能用过 WindowInsets。

Insets 自己指的是添入物或者是加入的一个范围。那么在咱们如今这个情境下,你们能够把它理解成是系统告诉你个人 UI 所在的位置区域,或者说是个人系统手势即将出现的位置。你能够经过这个值来移动应用内部的 view。让个人 view 和系统的 UI 不产生任何的冲突。

先来看第一类:WindowInsets 类,这个是咱们从 API20 就已经推出的。能够看到在下面这张图当中,导航栏式系统的 UI 部分,也就是绿色的那个部分,当应用去全屏写的时候,FloatingActionButton 被导航栏遮住了,那么这个时候我须要获取系统 UI 的位置,我能够用 getsystemwindowsinsets 这个值来移动个人按钮,从而避免任何和系统意外的冲突。

刚才有提到,在 Android Q上有新的手势导航。既然有了新的手势导航,也有了新的系统手势所在的区域。

最下面蓝色的就是曾经的 window insight 是系统 UI 的区域,三个绿色的部分就是今年新的手势导航所占的 insight 区域,左右两边是”返回“手势。最下面的 gestureinsets 就是退出或者是回到“最近使用过的应用”手势。

能够看到下面的手势区域是比以前的导航栏的区域要宽的,由于用户在想要退出的时候,他可能须要操做的空间更大。

在 Android Q 上面咱们也为你们提供了这样一个 API:getsystemGestureinsets,来帮助你们去得到如今新的手势导航所在的 insets 位置。

以前举的那个例子,FloatingActionButton 的问题,若是说你的应用和手势导航有一些冲突的,应该如何去解决呢?这里给你们分享一个例子,若是说应用是对图片处理的,例如说我看到这张图片我须要对它进行裁剪,那么任何一个用户看到这个界面,它天然会要采起的一个动做,就是从这四个红点当中去拖拽这张图片,从而进行裁剪。

一个很差的消息就是在 Android Q 上面,当用户去作这件事的时候,若是你没有进行适配,那么当他去拖拽,系统手势会有优先级。由于系统不知道你要用这些位置,那么怎么办?显然,当用户看到这个界面,他是会去处理这张图片的,因而咱们就给你们带来这样一个 API:setsystemGestureExclutionRects 传入的参数是一个 list,就是一系列的。rectangle 就是长方形,也就是咱们这里看到的那四个红色的点,由于在用户去拖拽那些区域的时候,用户是想要进行应用内部的手势操做,而不是开启系统自己的手势操做。为何只有红色的区域须要去覆盖?答案是确定的,由于若是拖拽出那个区域以后,系统手势导航只是在最边临界的位置,那么你用 API 的时候来得到系统的手势在哪里,针对性的把那个区域加入这样一个被覆盖的列表当中。这个方法是支持于你们使用返回手势的,这里有写退出应用的手势除外,由于在新的全手势导航下,用户离开应用,惟一的途径就是从最下面的退出手势,若是把这个手势覆盖了,用户就永远没法离开应用了。因此最下面的区域是强制不能被去除的。

若是你要告诉系统你要覆盖哪些范围,能够调用 setsystemGestureExclutionRects,若是你须要一帧一帧动态的去覆盖的话,你也能够把这个方法在 undraw 当中调用。

我在这里稍微停顿一下,由于以前听到有人说了这样一个方法:是否是说个人适配工做变得很容易,只要我应用内部的一些区域,我认为用户已经习惯这样用了,因此我去把全部的系统新的手势都覆盖掉。

咱们的建议是尽可能不要这样作,除非在有必要的状况下。由于很简单,若是你们有使用过新的手势操做,你会快注意到,其实返回这个动做是用户一天当中使用最多的一个动做,因此用户会很是快的习惯于新的手势操做,那么当它进入你的应用,忽然间他习惯的操做的动做被打断了,这确定不是一个很好的体验,咱们仍是最大程度 上想给用户一个很是一致的体验。

那么什么状况下你要用这个方法呢?就是我刚才举的那个例子,由于你们去修改图片这个例子,很明显的,任何用户当他处理这张图片的时候,他不会看到那些那四个位置,他不会想到要退出,而是很明显从 UI 上你给了用户一些提示:你如今要作的是我应用内部的一个操做,而不是说我开启系统的手势。因此但愿你们在作这些决定的时候,也思考一下用户会从哪一个方向来看待。

以前说到了有强制的手势区域,这边就给你们提供了这样一个 API 来得到被强制的手势范围,你能够调用 getMandatoryGestureInsets 方法来得到系统上哪一些区域是被系统强制的,也就是说你没有办法去覆盖它,给你本身应用有更高的一个优先级,在 Android Q 当中被强制的手势就是在最下面的退出应用区域。

稍微总结一下,getsystemwindowinsets 是咱们已经有了一段时间的 API,这个 API 返回的是如今系统的 UI 所在的位置,或者是说未来会出现的位置。当你在用有某些模式可能如今系统 UI 消失了,但用户可能会从新唤醒它。那么,经过使用 getsystemwindowinsets 你就能够得到系统 UI 的位置。

何时使用它呢?

特别是当你有一些 view 是须要点击的时候。由于你覆盖了系统的 UI,系统 UI 是要点击的,因此当你使用 getsystemwindowinsets 的时候,你是要处理须要点击的 view 的。若是说你有 view 是须要拖动的,你就可使用 getsystemgestureinsets,返回的是 Q 当中新加入的手势导航的区域,这个手势导航的区域,用户的使用方法是拖拽。因此,若是你有 view 是拖拽的话,你须要用这个方法来获取系统手势的范围,从而进行处理,最后就是系统告诉你们,你不能去覆盖的这样一个区域,也就是说你能够调用 getMandatoryGestureInsets 来获取你没有办法覆盖的区域。

常见情境

DrawLayout 优化

以前看到不少的朋友已经开始 Android Q 了,你可能会发现新的手势导航针对于 DrawLayout 抽屉式中导航栏没有很好的在一块儿合做。咱们也注意到了这个问题,因此在最新的1.10的版本当中,咱们对 DrawLayout 进行了优化,优化以后的 DrawLayout 的呈现形式是当用户第一次左滑的时候,你的抽屉栏会打开,而后用户再进行一次左滑,会退出当前应用。

这些对这些常见情景的优化,咱们还在继续的优化过程中,因此很是但愿你们可使用新的手势导航,并和咱们分享任何的反馈或者疑问,或者你有什么样常见的情境被新的手势导航影响了。

Carousels 相关

另一个常见的情境,若是你在使用 Carousels,应用内部有这种轮转式的显示的话,(一开始咱们听到不少的开发者都在考虑,由于用户要拖拽,我要把整个区域边上的区域所有都覆盖掉,但其实咱们推出以后,在内部作了一些研究,一些数据也显示,其实很快用户就习惯于这样一个手势操做,他明白他若是从最边界去拖拽的话,它是要返回的。其实用户对于新的的手势导航并无认为有很大的冲突。)咱们的建议就是若是你要用 Carousels ,不建议你们去覆盖那几个位置的手势导航,而是让用户去习惯于使用这样一个新的手势操做。

手势操做总结

今天介绍了不少关于全面屏和手势操做的建议,我在这里稍微总结一下:

一、随着新的全面屏导航的推出,愈来愈多的用户可能会使用新的导航方式,而且它会默认你的应用会和新的导航模式适配,因此若是你有任何不适配的地方,或者是故意不支持一些新的手势的地方,建议你们三思然后行。

二、有了全面屏就建议你们利用全面屏给用户带来一个更好的体验。紧接着为了帮助、确保像我刚才说的抽屉式导航等等这样的情境有很好的支持,咱们会继续在Jetpack和MDC当中为你们加入新的更新和支持,欢迎你们去使用它们。

三、若是你要去覆盖手势区域的话,请确保是在有必要的状况下你才去覆盖。

Android Q Labs 直播专题页面

Android Q Labs 开场演讲

Android Q 有哪些更新

Android Q 现代化您的应用

后台 Activity 启动的限制

Android Q 分区存储

Jetpack 更新

Android Q 在折叠屏设备的适配

通用系统映像介绍

Google Play 商店政策

Android Q 地理位置权限变动

Android Q 深色主题

Android Q Labs 总结演讲