Dark theme & gesture navigation (Google I/O'19)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Wait, did they just say 'Auto Night mode by time' has been depreciated?

Wow, I'm trying to figure out logical behind this...

πŸ‘οΈŽ︎ 59 πŸ‘€οΈŽ︎ u/Deeco7 πŸ“…οΈŽ︎ May 09 2019 πŸ—«︎ replies

Various scenarios including nav drawer talked of at around 36:38

πŸ‘οΈŽ︎ 12 πŸ‘€οΈŽ︎ u/_kushagra πŸ“…οΈŽ︎ May 09 2019 πŸ—«︎ replies

Nav drawer will automatically exclude gestures using the latest library released this week

πŸ‘οΈŽ︎ 17 πŸ‘€οΈŽ︎ u/armando_rod πŸ“…οΈŽ︎ May 09 2019 πŸ—«︎ replies

That BIG ASS back arrow, is a eyesore sometimes.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/exu1981 πŸ“…οΈŽ︎ May 10 2019 πŸ—«︎ replies

The new back gesture sucks with a case. The old back button with the pill was superior... They still have the P gesture pill as an option however mine isn't working the same. I liked how on P if you swiped right on the pill over and over it would consistently switch between the last two apps over and over. Now if I swipe right it goes to the app to the left in the tray, if I swipe right again it goes to the next app to the left and left and left. It no longer switches between the last two apps. Now I'm pretty disappointed in my Q Beta Upgrade on my Essential... Anyone else have this issue or is my phone broken? :)

πŸ‘οΈŽ︎ 12 πŸ‘€οΈŽ︎ u/iFonePhag πŸ“…οΈŽ︎ May 10 2019 πŸ—«︎ replies
Captions
NICK BUTCHER: Hello, good morning, everyone, and welcome. Thank you for coming to our talk. Today we're going to talk about two very highly requested user features which are new in Android Q, and that is dark theme and gesture navigation. My name is Nick Butcher, I'm an engineer on the Android Developer Relations Team. CHRIS BANES: My name is Chris Baines, and I'm also an engineer on the Android Developer Relations Team. ROHAN SHAH: And I'm Rohan. I'm a PM on the Android System UI and Launcher Team. NICK BUTCHER: We got a lot to go today, so let's get started. First up, we want to talk about the dark theme. Wait, that's better, dark theme. So why is dark theme important? We think there's three major reasons. The first up is supporting using your applications in darker environments. How often have you used your phone in a darkened room and been blinded by a bright white screen, which is not what you want? Supporting a dark theme enables usage of your app in many wider situations. Secondly, by lighting up less pixels on the screen, we've seen significant reductions in power usage. In fact, in our tests we've seen up to 60% reduction in power usage when the app is in the foreground, which can be a real user benefit. And lastly, dark themes can support accessibility while maintaining sufficient contrast ratios. They have less eye strain on the user so that could be used by certain classes of user much more comfortably. So for those reasons, we've introduced a new system setting in Android Q. So now under the devices display settings, you can choose between a light or a dark theme. You can also use a new Quick Settings toggle to quickly flip between those modes and the device will automatically kick into dark theme when your device enters Battery Saver. Now it's important to note the dark theme is actually a system wide setting, not just to the system UI, but it applies to all apps running on the device. And as such we think that users are going to increasingly expect your applications that you're writing to respond when they set this system toggle. So here for example I've got two apps running in split screen, and when I toggle into a dark theme, we can see that only one of them responds. And we think the users are going to increasingly expect your application to follow this. Now I've picked on Google Drive here because they're not currently supporting theme, but all Google applications are actually committed to update to support dark theme by the time Android Q rolls out. So this is only going to increase the user expectations. So as such, we strongly recommend that you look at supporting dark theme in your applications. Now we recognize that's going to be some work for you developers, us developers, and so as such, we're introducing something new in Android Q which is a feature called Force Dark. Now Force Dark attempts to automatically apply a dark theme to a light theme application. Well, let's take a look. So here's the Google I/O application and here it is with Force Dark being applied to it. And it does so in a kind of intelligent way. It runs at rendering time and actually inspects the views that it's rendering and tries to smartly work out which ones should be inverted in order to run dark. It even does some clever stuff like looking bitmap drawables and tries to work out if there's a variation in the hue, is this some kind of photographic data and not invert certain kind of images. So it's got some smart heuristics in it. Force Dark is opt in, you have to turn it on for your application. And you do so like this, by setting Force Dark allowed to true. Here I'm setting it at the theme level for my entire application theme so it will apply everywhere throughout the app. But you can choose where to turn it on so you could turn on just for one or two activities and use it almost as a kind of migration to help you rapidly adopt a dark theme. So Force Dark can help you to rapidly adopt dark theme, but we still actually recommend that you look into designing a custom dark theme, which you can do so using themes and styles. The reason for this, well, there's two main reasons this really. The first one is that Force Dark is only available on Android Q, so it's only going to benefit users on Q forward. Whereas implementing a custom dark theme is actually using the standard Android styling techniques. You can roll out your dark theme into all kind of major API levels. The second reason why we think it's important go custom is it gives you utmost control over exactly how your app renders, which is what you want, right? You don't actually get to hook into how Force Dark will darken your applications or how it will change the colors. So if you want control over, if your designers wants to be able to control the exact shades of blue that they're [INAUDIBLE] here is going to change to, for example, then a custom theme is the way to go. So to help you to design for dark themes, we've just released this week some updated guidance on the material.io website, which covers how to generally design a dark themed application. With specific guidance around important areas such as accessibility and guidance on how to adapt your apps color system to work under a dark palette. In fact, there's another session at Google I/O right after this one on stage one which is all about how to design for the dark theme. So to implement a dark theme, we recommend that you take a look at the AppCompat material design components libraries which Chris is going to talk about now. CHRIS BANES: Thanks Nick, so DayNight is a feature in AppCompact which we've had for a number of years now, which allows you to easily implement one of those custom themes in your app. Now the way it works is by enabling the Night Resource Qualifier, and it works back to API 14, which Android 4.0. We've been hard at work for the past couple of months to improve it and that is available in AppCompact 1.1, which is available now. To implement a theme using DayNight, the first thing you need to do is change your theme parent to be one of the themes that are compatible with DayNight variance. If you're using materials on components, which I'd recommend you do, it also provides a DayNight theme in its version 1.1, again, available now. As we mentioned earlier, AppCompat enables the -night resource qualifier to work. And that is exactly how the theme is implemented. You can see in our default configuration that DayNight points to Theme.AppCompat.Light, which means that when the light theme is selected, we'll use a light theme. And when in our night configuration, in values-night, it points to a Theme.AppCompat, which means we'll go dark. The next thing we need to do is tell AppCompat what mode to use. Now we have two APIs for that. The first is setDefaultNightMode, which is used when you want to set a mode across your entire app, so all of your activities. If you need a local override in a specific activity, we have setLocalNightMode. Now one thing to note is that the values you set on these APIs are not persisted. So therefore, you need to set-- use the method whenever your app process is brought up. Usually you'll do in you application object. Using those APIs, you need to give it a mode. And we offer four main modes. The first is MODE_NIGHT_YES, which means always dark. MODE_NIGHT_NO, which is always light. FOLLOW_SYSTEM, which will follow the current system setting. Now on Q because we have a new system setting, which is great, it will do that basically. Whenever the system setting is changed, your app will follow it. When your running on devices before Q, so Pie or earlier, it will usually default to a white theme. The next new mode is called AUTO_BATTERY, which we've added in AppCompat 1.1. And that goes dark whenever battery saver feature is enabled. And it works back to API 21. So you can see an example where a device is going into battery saving mode. When that happens, your app will automatically go dark. When the user plugs the device back in, it goes back to charging, and therefore we leave battery saver mode, like so. We'll automatically go light again. The final thing to check is to make sure that your activities are extended from AppCompat activity. This may sound super obvious, but its something which is easily forgotten. So as I said earlier, we've been hard at work over the past couple of months to improve the DayNight feature. And so I'd like to take through some of the things we've done. So one key change is that setDefaultNightMode now recreates any visible activities. It previously didn't do this and you had to do all that work yourself, whereas we now do it for you. We also have an incompatibility with WebView. Whereas if you're using DayNight and then later inflated WebView, we'd reset the theme and then things would go very wrong. And that's now fixed. [AUDIENCE CHEERING] The final thing is that MODE_NIGHT_AUTO_TIME is now that deprecated. As I said earlier, we've been hard at work over fixing many, many bug fixes, which you've all raised. So hopefully, if you've had any issues, they're fixed. That leads into an app theme setting. So to support user customization, we recommend providing a way for users to choose the theme that they want in your app. An example could be an e-book reader. If a user knows that they are always going to use the app at night, and they always want it to be dark, you want to find a way for the user to select that. We recommend there be three options when we're [INAUDIBLE] Android Q. Light, dark, and then system default. System default being the default option for your app. If you're running it on Android P or before, because we don't have that system setting, the options are slightly different. They're now light, dark, and set by battery saver. Now the keen-eyed among you will notice that those options map pre-directly to some of the AppCompat modes and that's totally on purpose. There's a 1-to-1 correlation between those options and the modes we actually have and we offer you. So now I'm going to hand it over to Nick to talk about how elevation works with dark theme. NICK BUTCHER: Elevation. So in material design, elevation is a key concept for showing the importance of some content in your application, by changing the elevation of the surface and for hinting at interaction cues. Now in light themes, this is represented with a shadow. And as the elevation raises up, the shadow becomes more diffuse. But when you have a dark background, like in dark theme, this can be harder to see. And as such, we're introducing the idea of elevation overlays. The idea here being that, as the surface raises up to get closer to the virtual light source, the actual surface color itself changes, as if there was a semi-opaque white layer on top of it, which gets more opaque as you raise up in elevation. Don't worry. We're not actually doing overdraw of the white layer on top. This is actually, we kind of blend down the color and use it as a tint on the background color. So to use elevation overlays, then all of the components in material design components version 1.1 onwards will support this out the box. These are the components which use the color surface attribute for the background color and support elevation. And as such, just by setting the elevation on the components, you'll get this surface overlay behavior. But if you want to build this behavior into your own custom components, there's a couple of options. Firstly, you could use the MaterialShapeDrawable, which is the kind of background drawable which powers a lot of materials. Shape theming, as well as this material elevation overlays. And you can use these in your overviews as well. It's been augmented with new API, such as createWithElevationOverlay or setElevation or setTranslationZ, which will give you this overlay behavior. If you can't use the MaterialShapeDrawable for some reason, you can instead take a look at the ElevationOverlayProvider class, which is what MaterialShapeDrawable uses under the hood. This gives you lower level methods, such as working out the surface color for a given elevation, which you can then use in custom drawing the same. Now, implementing dark themes, as we said, comes down a lot to good hygiene with your applications, themes, and styles. And we've given you some specific tips and gotchas when implementing dark modes. Quite commonly, we've seen an issue where applications, which are designed like this for a light screen, where they might have dark text on the light background. When they apply a dark theme to the app, you see an issue like this, where you end up with, say, dark text on a dark background, which you end up not being able to read. Or perhaps the text correctly inverts to light, but your background remains light. So these are common issues that we see in applications supporting dark theme. And generally when this happens is you've made some assumption that somewhere in your layouts about being running under a light theme. And you've kind of hardcoded some colors, like hardcoded a white background or black text in this case. Now you're probably not hardcoding things like this in your layout, but you're probably using some kind of color resource. And this is essentially the same. If you only provide color value in the default configuration, this is essentially the same, that it's not going to respond when running under dark theme. What you need to do is provide an alternative color when running under the night configuration here in the values-night folder. And as such, these colors will then respond to the theme change. Better yet, you can take a look at using theme attributes. Theme attributes are essentially semantically named colors, which have different values when running under a light or a dark theme. So here for example, I'm changing that hardcoded background from white to materials color surface color, which is a kind of background color. And so that will flip from white in a light theme to a very dark gray when running under dark theme. Or likewise, I'm using the platforms text color primary here for the text color, which will give you the inverse of that. So it will be dark in a light theme and light in the dark theme. In fact, if you take a look at the material color system, it has lots of these semantically named colors, which are super useful for using in your designs. So you're probably familiar with things like color primary, color secondary, color accents, and so on. But here's the surface color that we looked at before. But they also provide a series of on colors, so colors which will contrast on top of the relevant color. So On Primary, On Secondary, On Surface. So for example, the On Surface color is a color which will always contrast on top of that background Surface color. So we can use this in combination with a neat trick that colors state list provides to great effect during dark theme. So for example here, I am using the fact that color state list lets you separate out the color from the alpha channel and define them separately. So I'm grabbing the colorOnSurface, so something that will always contrast the surface color, and applying an alpha modification to it. So this can be super useful if you want avoid having 50 different shades of gray in your colors XML file that you are scared to kind of update, because you don't know where they're going to use. Instead of that, if you can reference these colors always guaranteed to be the right color to contrast, given a different theme. And just apply an alpha modification. It can be super useful. One caveat is this alpha kind of modification was introduced in API 23, Marshmallow. So if you want to use it beforehand, make sure you're using the AppCompat resources path, or loading it like this in code. Similarly, whenever you're loading colors in code using context compact, .getColor, for example, be wary that you want to ensure that those colors as well have night configurations. Or better yet, you might want to do something like this code here, which is querying the current theme for a theme attribute. So this is how you can get access to something like text color primary or color surface in your code. Another class of issues we've seen is around drawables. So if you have drawables, you probably want them to be showing up, like these light drawables here, but you might encounter similar issues, as we saw before, where you might end up with dark-on-dark. Or you could look at providing completely separate versions of the drawables under the drawable-night configurations. A better way is actually probably to look at tinting, because usually these are monochrome icons that you just want them to change the entire color of them. So you can tint at a couple of levels. You can either tint at the view level here. So here I am going to tint whatever drawables giving me with whatever colorSecondary is for the current theme. So it'll update it depending on the theme. Or hopefully you're using vector drawables throughout your app assets, which natively support tinting on the root element of the vector. So here I'm setting the colorControlNormal theme attribute, which is the standard kind of gray icon color. So setting this means your icons will always be the exactly right color. Or if you're working in code, you could also use the DrawableCompat class, which can apply a tint dynamically to a drawable as well. And lastly, it can be handy to work out if you're currently running under a dark theme, which you can do with some code like this, which actually looks at the configuration's UI mode and checks whether this is currently in night mode. So this is useful for querying whether you're under night mode and maybe branching your logic or setting a different tint on a drawable or some such. Those were just quick tips about working with themes and styles. We could spend the whole talk talking about-- well, you could-- talking about themes and styles. But we've actually already done that a couple of times. So I highly recommend you check out these with resources on that. Lastly, I want to revisit Force Dark and talk about how it can help you to migrate to a dark theme. So here's an application designed for a light presentation. And when we apply Force Dark to it, we can see it's generally done a pretty good job of it. It's is generally inverted a lot of the colors. There's a few opportunities. It could be better in my opinion. In fact, if we compare it to a custom dark theme, which I designed, you can see a few things which force dark hasn't done quite right. For example, if we zoom in on this drawable on the left, which is indicating the depth of a threaded conversation, Force Dark has made it a bit too light for my tastes. What you can do in these situations, is you can set the forceDarkAllowed to false on any given view or view group and disable the Force Dark behavior just for that part of the hierarchy. But remember, when you set Force Dark to false, the general configuration is still running under the night mode. And as such, we can use things like tinting. And this tint color will give you the right color for a theme, so this will respond to the night configuration. So check out Force Dark. Like I said, it's one line change in your theme to set it for your application. Or we've actually introduced a new developer option where you can force the entire device into this Force Dark mode. So if you want to check it out now, if you're running Beta 3 or newer, you can see how your app responds to Force Dark. So next up, Chris going to introduce some common scenarios we're seeing with dark mode. CHRIS BANES: Thanks, Nick. So the first thing we're going to to talk about is web content. Now the good news is that WebView works seamlessly with Force Dark. So if you're opted into Force Dark when you're running under Q and you have an example here. So we have an app here, which you load into Google.com in a WebView. And we've enabled Force Dark on this app. And when we go into night mode, it changes the WebView as well. It also works in Chrome, Chromium-based browsers, and WebView. So soon actual web content will be able to support dark theme natively, using their the CSS media query called prefers-color-scheme. We've also added dark theme support in custom browser tabs. And by that, we mean the UI around it. So we have a new method on Custom Tabs intent called setColorScheme. It takes one of these three options. Now when-- here, we're in light theme, but when we go to dark, it looks a little bit like this. Now you'll notice that the content itself doesn't have Force Dark applied or anything like that. That's because we're aligned on the web content itself to use that media query we just spoke about. Now MapView itself doesn't support dark theme out of the box, but we can easily make it do so by using its custom map styling functionality. Now custom map styling allows you to specify the colors and text and stuff of a map via JSON file. You can see a link to a website we can actually download some map styles that we provide for you. I think there's nine styles on there. Some are light, some are dark, but you can also customize it to your needs. Now, we can actually use that feature by using the -night resource qualifier that we spoke about earlier to make MapView sport dark theme natively. So in our default configuration, we'll put a light-styled map in the JSON file in res/raw. And then in res/raw-night, we'll put a dark-styled JSON file. And that way MapView will automatically load the correct map style and then use the correct colors. NICK BUTCHER: Another issue we see when adopting dark themes is with illustrations, which you're probably using in empty states or maybe onboarding or closing your applications. If you just use the same illustration design for light theme under a dark theme, you can see too high contrast, where these colors are, like, way too saturated and they contrast very highly on these darkened backgrounds. We recommend that you provide an alternate version when running under a dark theme, which is more harmonious with the darker backgrounds. Now again, you could just provide an alternate version of this drawable, so you have two versions of very similar drawables in your application, but a better way to do this might be to use an effective drawables ability to reference color resources. The individual fills or strokes of paths. And as such, you can vary just the colors, when running under a night configuration. So this way, you only have to ship one version of the drawable, but have the colors respond to when it's running under a dark theme. Next up is notifications. So notifications, when running under a dark theme, will respond and go dark. So if you're using any of the notification templates, these will work just out of the box. But if you're using a custom layout, you're setting a custom layout, than all the rules we talked about before about sliding still apply. So don't assume it's running under a light mode. Don't hardcode colors. Use theme attributes. In fact, I'd encourage you, if you're sliding any text in particular, to look at the subclasses of the notification text appearance, so that your text will mirror that of the system's notifications as well. So that was dark mode. Our take aways really are that users are going to increasingly expect your applications to support dark theme, so really, really do take a look at supporting it as well. Use AppCompat, DayNight, and material design components, which have lots of built-in support for implementing this in your applications. And be sure to look for these latest versions, these 1.1.0, because there's been lots of improvements and bug fixes in them. Consider Force Dark as something to help you rapidly adopt a dark theme. And maybe use it as a migration tool, so you can enable it for certain activities and then roll out custom themes gradually. And theme attribute all the things. Don't think about being hardcoded in a single configuration, a single color scheme. Be very flexible. Whenever you see a hardcoded color or color resource, if only a single version, see that as a red flag. So now I'm going to head over to Rohan, who's going to tell us all about gesture nav. Cheers. ROHAN SHAH: All right, so I have the benefit of telling you all about gesture nav. A few of you might have played with it already on Beta 3. If you haven't, make sure you give it a go. It's out there in settings. You can search for fully gestural navigation. But I'll do a quick refresher of what it looks like right now in Android Q. So we're adding a new nav mode, if you haven't already heard, in Android Q that replaces the beloved three buttons with three glorious gestures. And here's what they look like. On the left, you can see that swipe up from the bottom will become the gesture for home. Swiping up and holding in the middle will take you to your recent and/or overview. And on the left, you can see that swiping in from an edge will take you back. Now the one thing that this movie doesn't really do justice is that we're also introducing swiping left and swiping right in order to go back. We think it's a super awesome experience. Internally, we love it. We've heard really great feedback. We definitely want to hear how you feel about it. But definitely give it a try. So a big question we've gotten is, we're introducing another nav mode in Android, what do we do? Like, we're developers, what are you trying to do in Android? So I want to talk about that a little bit really quickly. In the future for Android, we're going to be supporting two nav modes moving forward. The first one is three buttons. You know, Android users love three buttons. We know that it's super usable. And it also addresses a lot of accessibility needs that gestures just cannot. On other hand, we also know that there is a lot of desire for gestures. So we will be supporting one gesture mode, which is what you saw, moving forward in Android. And only that one. I want to take a quick step back and talk about why we're doing this now, before we dive into the details for developers. And talk about user trends here. So Dan Sandler talked about this in his talk in what's new on Android. But users increasingly want immersive experiences in Android. And one thing that device makers have done is try to approach this from a software side. And what they've done is built their own gesture nav. And every device maker has a different impression of how gesture nav should work. What we recognize, on the platform side, is that kind of gets insane for a developer, thinking about n different gesture navs when you're trying to develop. Just design for, test for your app, just kind of gets insane. So with that in mind, we introduced this gesture nav in Q. And we're going to be standardizing the ecosystem as of Q on three buttons and our model moving forward. And just want to elaborate the problem here. You know, there's a lot of different gestures. These are just some of them. Dan's talk had different swirl gestures and maybe a knock knock does something different, but we do want to unify that core set of gestures, back, home, and recents. Taking a slightly different spin on this, why should you care as an app? I'm going to regurgitate that immersion bit, but flipping this a little bit, there is an opportunity for you, as an app, to delight your user by bringing this immersive experience to your app. And making sure that it's compatible with this new nav mode. In terms of compatibility, we recognize that there may be some conflicts that you will need to handle as an app. And we'll talk about that coming up. Cool. So how do you make your app nav-ready? And nav just means, you know, any nav mode, 3 button, gesture nav. How do you prepare for this immersive experience? And more importantly, how do you prepare for gesture nav? There are three things you need to do. The first one is making sure that your app goes edge-to-edge, which Chris will explain a little bit more. The second thing you need to do is leverage insets, old insets and new ones that we're adding, to make sure that any kind of critical content is in a safe place and is in optimal positioning. And the third and final thing is handling conflicts. If you do have a conflict, how do you handle it, and how can you override certain gestures so you can bring a better delightful experience to your app? Cool. So I'll hand it over to Chris to talk about edge-to-edge. CHRIS BANES: Thanks, Rohan. Yeah, so what is actually edge-to-edge? Well let's take a look at a typical app when you're running Android Q today. So here you can see the bounds of the app are actually below the status bar and above the navigation bar. So what do you want on Q? Well simply, we want the navigation bar to disappear, allowing your apps content to be displayed behind it, to create a more immersive experience. When it scrolls, it looks a bit like this. So as recommendation, drawing behind the navigation bar is now strongly recommended on Q. It's optional before Q, but one thing to note is that a lot of the APIs and how you do this actually works back to previous versions of Android. So if you're going to put the work in for Q, it's not that much more work to do it for previous to Q, as well. Now let's take a look at the status bar. Now similarly, we actually want the status bar to go away as well. Again, allowing your app content to be displayed behind it, creating a more immersive experience. And you'll hear the word immersive a lot in this presentation. So now our app looks a little bit like this when it scrolls. Again, drawing behind the status bar is now recommended on Q, and optional before Q. So if we take a look at our bounds, they've come from here to here, which is where we get edge-to-edge from. So let's take a look at now about how much actually implement this stuff. So the good news is that from Android Q onwards, the system is now responsible for recoloring the system buttons and the handles. So you can see here, an example, where as we scroll, that navigation bar handle at the bottom is changing color based on the content behind it. Now the recoloring can take the form of both dynamic color adaption, which you've just seen. Or it could be static coloring on less powerful devices. When you're running on older platforms, because that recurring doesn't happen, we recommend that you set a translucent nav bar color, so the user can actually see those buttons. So to really make your app go immersive, there are three things you need to do. The first is change your system bar colors. Second, request to be laid out fullscreen. And then the final thing is to avoid any overlaps with your views with the system UI. So let's go for it. The first one is the change in the navigation bar color. Now, we have this attribute available in Lollipop onwards, which we can use. And we're just going to set it to transparent. When you run on Pie or before you should use a translucent color as we just mentioned. The next thing we need to do is request to be laid out fullscreen. Now we're going to use the infamous set systemUiVisibility method, with a number of flags. The two flags we need are FLAG_LAYOUT_HIDE, and that tells the system to lay as out as if the navigation bar wasn't there. And a second is LAYOUT_STABLE, which is special flag that tells it to lay us out at it at our most extreme. If you also want to be displayed behind the status bar, there's an additional flag you need to use called LAYOUT_FULLSCREEN. Now when we lay out fullscreen, we don't want our views to be displayed behind the system bars. And that is where insets come into play. Now insets are a collection of values which tell you how much to move or inset content by. Now what views you move, how much you move it by, depends on the inset and its purpose. And you might have seen the in WindowInsets class. There are a number of types of insets. The first type are called system window insets and they tell you where the system UI is being displayed over your app. They are commonly used to move views that are not obscured by any of the system bars. So here you can see a FAB at the bottom right. So we blow that up a little bit. Typically a FAB will have a 16 dip margin applied to it. And you can see that they are denoted by these blue bars. So actually, in gesture nav, it's not too bad. It's only obscured by the bottom 2 dips or so. So we'll use the system window inset to actually move that up. But in free button navigation mode, it's actually a lot worse, because the navigation bar is taller, our FAB is a lot more obscured. So by using the system insets, we can move out and make sure the user can actually click it. So as a recap, system window insets are used to move clickable views. The next type are called system gesturing insets. And they're new in Q. Now they represent the areas of the window where system gestures take priority. Visually, they look a bit like this. So let's go through them. They include the vertical edges for the back gesture. So if the user starts dragging from an anywhere in the left and the right hand zones, the back gesture will start triggering. And again, on the bottom side, where the home gesture takes place, again if the user start dragging there, the home gesture will take will take priority. Now as mentioned, system window insets we use for clickable views, system gesturing insets are used for draggable views. We'll go for example a bit later. The next and final type are called mandatory system gesturing insets. And they're a subset of system gesture insets which define the areas which cannot be used with exclusion APIs, which Rohan will talk about in a minute. Now in Q, they are currently only used for the home gesture, because that's a protected gesture that users should always be able to exit your app. ROHAN SHAH: Right. CHRIS BANES: Maybe not over to Rohan. So as a quick overview, system window insets are clickable. Gesturing insets are draggable. And mandatory system gesture insets are used to check the exclusion APIs. Now actually over to Rohan. ROHAN SHAH: There we go. So the third and final thing in making your app nav ready is overwriting system gestures. So Chris already talked a little bit about some of the system gesture insets and ones that are mandatory. But I want to quickly talk about what kinds of conflicts you may have to handle. And where you may need to override. So any sort of horizontally draggable content that resides in those back zones, within those system gesture insets, is an area where your app may have conflict. I want to give a quick example here. But I opened up a photo in the Photos app and I wanted to crop a picture and crop my buddy out. And you'll realize that the crop handles, the little circles you can see on each corner of that square, are awfully close to the edge. And unfortunately, those are in the system gesture insets and in that back zone. So there are other examples like this, you know with sliders, seek bars, video seek bars, for example, other drag handles, et cetera, that your app may need to be aware of. Great. So how do you override some of these gestures? How do you make sure that your user is able to use those crop handles, et cetera? So there is a new API available in Q that will allow you to opt out of, at least the back gesture. Home is still a mandatory area. We know that's the only way a user can leave your app, so we're not making that opt-out-able. But basically how the API works is that you can specify a rectangles on screen where basically you'll get touch events, instead of the system consuming it for back, or for any gesture in that area. One quick word of caution. This is pretty powerful. One quick word of caution here is that, be really careful when using this. Users expect to be able to go back. It is one of the most frequently used system actions. I think it's used twice as much as home. And if you suddenly break that and decide to take over the entire edge, for example, your users might get frustrated. So be really careful when using this. And make sure that you have very clear visual affordances, such as the drag handle, that indicate that you can actually swipe there. And a user will start interacting with app content instead of going back. Taking a quick look at the API, it's going to be in the View class. And it's called setSystemGestureExclusionRects. And it takes in a list of rectangles where your app will get the touch events first and only. You can use this in onLayout, if you have kind of static content that isn't really shifting. Or you can set this in onDraw, if you want more kind of real time frame-by-frame updates. Cool. So let's talk about some common scenarios with all of these three pieces of guidance. And Chris will take over here. CHRIS BANES: Right, so the first scenario we're going to look through is scrolling views. Now, as you can see here, content should be drawn behind the navigation bar as the list scrolls, but when they user reaches the end of that list, that final item should still be above the navigation bar, allowing the user to interact with it. As you can see here. When we reach the end of the list, we still want those bottom items, lightning talks, in this instance, to still be above the navigation bar, so that users can interact. So a common way to achieve this would be through padding. And we'll pad our scrolling view using the system window insets that we spoke about earlier. Here's a quick code example. We'll set an on apply window insets listener, and then we'll waive some insets. And then we'll just set the pattern on the scrolling view, in this it's the recycler view, using the system window inset pattern. And the final thing we need to do here is something called clip to padding. Now by default, whenever a view group sets padding, or has padding set on it, it will clip its children. Now that's because that's the whole effect we want. We want our children to be displayed behind our pattern. We need to turn that feature off. So recycler view, list view, and all the other scrolling views support this. So just need to set to false. The next scenario is all about navigation drawers. Now if you've tried Beta 3, you'll probably have noticed that a lot of apps use navigation drawers and it can sometimes get a bit funky. So DrawerLayout will automatically exclude the correct edges as necessary. So here you can see, in the Google I/O App, that when the drawer is closed, it will open. And the next gesture, when it's open, the back gesture will actually take preference. Now to use this, you need updates on 1.1.0-alpha01, which just released this week. The bottom sheets, generally, we want to avoid views near the vertically scrolling gesture zones. But bottom sheets are obviously a pattern which a lot of apps use. So for collapsible bottom sheets, we want to make sure there's enough content above the navigation bar for the user to be able to actually drag it. So here we're looking at an example where we haven't done that. And you can see that as the user tries to drag the bottom sheet, actually the home gesture is going to takeover. And we don't want that obviously. So one way we get around it is by using the system gesture insets to increase our content size, allowing enough space for the user to actually drag it as so. Since there's a code, here we're using the bottom sheet behavior from material on components. And it provides peekHeight. So that's the amount of height available when it's collapsed. So here, again, we're using on apply window insets listener, we'll grab our system gestures, and then we'll just increase that peek height. Now it's also available in ViewCompat in the core library in AndroidX. And again, we've released a new version this week, called 1.2.0-alpha01. But remember, users can always swipe to go home by swiping at the bottom of the screen. So even though we've done this and we've moved the peek high up, users can still accidentally trigger this gesture. And that's obviously annoying for users. So draggable content near the gesture nav zone is possible, but be careful if you're going to do it. One thing also to say is to try and make the draggable content more obvious to the user, so they drag the right bit. So here you can see that the actual header bar is fully opaque, the content below it actually has an alpha effect applied, trying to guide the user to the top section. The next scenario is carousels. What that would mean, view pages, or any horizontally scrolling lists, like recycler views. Now one thing we don't really want is for apps to set exclusion rects everywhere, because that's a problem for users. If an app sets exclusion rects all across the left and right zones, the user is not going to know where they can actually trigger back. The final scenario is what about landscape? So if you've gone edge-to-edge, what we talked about earlier, in landscape, when in button mode, what we'll actually get is, which obviously isn't great. So you can see that the button options are actually obscured by our apps content. Now this doesn't happen on gesture mode. You only have this on button mode. So if you have content which starts near a vertical edge, think about padding all of the content in horizontally. And one thing to note also is make sure you test your apps both on button modes and also the gesture nav modes. As a code example, it's pretty easy. You just need to find a view somewhere [INAUDIBLE] near the top, set an on apply window insets listener, and then set the left and right padding based on the system window insets. And that's safe to use in all our orientations, because it will always give you the right values. And once you've done that, you're looking a bit like this. I just want to say, we are adding more support in our AndroidX libraries, Jetpack libraries, to make this a lot easier for you. The examples we've just gone through are just trying to show you how we've tried to implement this in our libraries. But if you have custom views, obviously you're also going to need to do something similar. Now if there's difficult patterns that you're finding, please raise them, so we can try and build better support for you via the bug tracker. So a quick TL;DR, users will expect that to work on all navigation modes. Please support it. Try and create immersive UIs, because it's giving your apps more real estate to display in. Proactively update the Jetpack and MDC libraries, because we are going to add more support as time goes. And only use the gesture exclusion API if you really need them. They're really meant as an escape hatch for your apps. And finally, let us know about troublesome scenarios via the issue tracker we just spoke about. Thank you very much. [MUSIC PLAYING]
Info
Channel: Android Developers
Views: 36,366
Rating: 4.8472729 out of 5
Keywords: type: Conference Talk (Full production);, pr_pr: Google I/O, purpose: Educate
Id: OCHEjeLC_UY
Channel Id: undefined
Length: 41min 19sec (2479 seconds)
Published: Thu May 09 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.