hey everyone I'm Ian and I'm a developer relations engineer on the composed devil team and I'm Conrad a software engineer on the material team with more and more foldables tablets and Chromebooks in the hands of your users and with different ways of using them making sure that you handle window sizes becomes crucial for your user experience for example some users take advantage of larger screens and use split screen mode and Chromebooks can run apps in free form Windows if you're only ever thinking about compact window sizes in portrait orientation it's really easy to make assumptions
that aren't great for users to reach when displayed in bigger Windows even common decisions like making everything full width can lead to some unsightly stretching for years we've recommended the apps use Windows size classes as the opinionated break points for their UI these let you group UI Behavior without worrying about this specific underlying device and today I'm here to tell you well actually Conrad do you want to tell everyone of course today our latest guidance is still use window size classes as the opinionated break points for your UI that's right our guidance is the same
but we've been working on making it easier to implement common adaptive layouts with some new apis that under the hood take advantage of window siiz classes for you let's dive in yeah let's do it first of all we have great news for you we've released the materials through adaptive layout libraries into beta that means there are a variety of adaptive apis ready for you to use this libraries provide composes to solve exactly the types of issues we were talking about each of the new scaffold makes it easier for you to make your UI look good
across window sizes I'll start with the navigation UI which is handled by navigation Suite scaffold material guidelines recommend using a navigation bar at the bottom of compact width Windows such as most phones and a navigation rail at the side of medium width and expanded width windows but it used to be up to each app individually to handle swapping between these components and it just took a little code well little if your font size was small enough and I did have to skip a few things here now we have navigation Suite scaffold that does this for
you by automatically observing the window size class for your window let's take a look this sample app has an ene that represents the navigation destinations it contains a label icon and a Content description for that icon now that we know what the possible destinations are the app needs a way to remember which is currently selected so we use a remember savable here you could also use state in a view model calling the navigation Suite scaffold requires two things the actual navigation items to the display and whatever content you want to show based on that selection
this could use your navigation library or a simple when statement to call a particular composable back to our navigation Suite items iterating over each destination the item function is called setting the icon the text label to display whether the item is the selected one and what to do when clicked with just these lines of code the app will automatically change between a navigation bar and a navigation rail based on the window size class that also means it will handle Dynamic changes to the window size at runtime for the vast majority of apps this is all
you need but you can customize it for different behavior for example the default for expanded Windows is to show a navigation rail because an app showing multiple panes for expanded sizes it might not have enough room to show a permanent navigation drawer instead of a rail but maybe your app uses a single pane for a feed so you do want to display a permanent navigation drawer for expanded Windows how can you override the expanded window Behavior but still have the default scaffold behavior for other window size classes you can tell the scaffold what layout to
use with the layout type parameter the default calculates the right navigation type this function takes a single parameter a window adaptive info that class represents the current window size and posture information calling current window adaptive info will give a new instance of this class that can be used to determine which navigation UI to use in this case if the window size class for the width is expanded custom nav Suite type is set to navigation drawer otherwise it falls back on the defaults passing the custom nav Suite type into the navigation Suite scaffold now makes it
so that for Compact and medium width window size classes it will still use the default but for expanded it will use navigation drawer despite completely changing the UI that will be used in expanded Windows nothing else needs to change the same navigation Suite items can be used for navigation bars navigation rails and navigation drawers once the navigation UI is out of the way it's time to focus on the content on the phone you usually organize your app flow through screens for example clicking on an item on your list screen brings you to the detail screen
however to make your app be adaptive let's try to think about your app in terms of pens instead of screens you don't have a list screen you have a list pen you don't have a detail screen you have a detail pen multiple pens can show at the same time in one screen depending on the current window configuration for a compact window size class such as a phone you might only display one pen for an expanded window size class you might show two or more pens at the same time you may want to ask how do
I decide what should be a pan our suggestion is simple any destination you can navigate to is a pen just like your apps navigate through screens nowadays in the Adaptive world you navigate through pant our common pattern for organizing your app in pans is the least detailed Canal layout in a smaller window the list pen would take the four window and tapping an item would navigate to the detail pen in a larger window the list pen and detail pen should show side by side instead tapping an item in the L pen will leave it selected
while the detail pen updates with the appropriate content another example is the supporting pen that layout has a primary pen with the main content and a supporting pen with some additional related info for the least detail pattern use the least detail pen scuffle for the supporting pen pattern use the supporting pens scuffle their apis are similar so let's look at list detail pens scuffle in detail here's how you can use our least detailed pens scle composable your most important mission is identifying navigation destination in your app and putting them in the corresponding pens for example
to create a mail app you may want to put your mail list in the list pen your current mail content in the detail pen next to give you the best experience let's wrap the pen content in animated pen a composable that provides a nice default animation during pen switching you may notice that we are using streen scel scope here don't worry too much about it it's meant to provide Advanced contextual info to your content composes if you don't need very sophisticated layout customization you can ignore it for now and that's basically it let's list detail
pens SCU will do the magic and you will have an Adaptive app it will show either one pen on a smaller window or both mail list and content side by side on a larger window this looks great and you mentioned pain switching oh yes that's why we have the navigation API when you can have multiple destination showing at the same time navigation become a really complicated problem and the Navigator apis will help you deal with all the comp acces to use them just create a remembered instance of the Navigator and invoke the scaffold composable with
it when you need to navigate to another pen call navigate to back handling is also straightforward just Co navigate back in your back Handler oh one thing to notice is that you should check if your scao can actually navigate back before you consume the Back event let's talk about more advanced uses of the mat material 3 adaptive layout apis the Navigator provides a directive and value but we didn't cover what these are in most cases you can just use the defaults the value provides a pain adapted value for each pain currently these will either be
expanded or hidden but we may add additional options in the future the values for each pain are accessed as primary secondary and tertiary since the same class can be used for supporting pain scaffold these equate to the detail list and extra pain respectively a great use of this data is to make conditional decisions in your UI based on what pains are showing for example if your detail pain wants to know if the list pain is hidden it can check the scaffold values secondary field this ensures your pains code doesn't have any awareness of the logic
which decides which pains to show if you change that logic this code still works correctly the other part is the directive which which you can use to change that logic it's the pain scaffold directive that controls things like how many partitions the available area split into and how much space should go between them to better understand this let's create this example we want to show one pane for compact two for medium and three for expanded like this image we also want to add gray padding around the entire scaffold color each pane differently and mark the
spacers between each pane black let's customize the directive first we need a function that will return our custom pain scaffold directive our custom Behavior will look at the window size class for the width and decide on a single partition for compact two for medium and three for anything else we can return a new pain scaffold directive using our calculated horizontal partitions and a spacer of 16 DP between each pane we only want the screen to split horizontally so we pass one for the max vertical partitions and set that spacer to zero DP the final value
exclude bounds allows you to pass in areas that the directive should be aware of for example you can pass in where the hinge is to avoid placing important UI there in this case we're just displaying some colored boxes so we can pass an empty list back where we want to use the custom directive we call the same remember function but pass in our custom directive for the scaffold directive parameter when we create the list detail pane scaffold we're going to use some modifiers to better see what's happening first we'll apply a gray background then we'll
pad the whole scaffold by 64 DP and finally we'll set the background to Black since the order of modifiers is important in compose that means the black will only apply to the area that's 64 DP in from the edges and the rest will be gray now we pass in the directive and value since we only overrode the directive when creating our Navigator the scaffold value will use the default and the scaffold directive will be our custom one last we set some content for the panes to make it easier to understand what's going on here we're
just going to use a composable that draws a full-size box in each pane with red for the list green for the detail and blue for the extra Pain by creating that custom directive and using in our list detail pane scaffold here we can observe that the behavior is different from the default in a compact window like a phone we still just see one pain notice that we see the gray outside that we applied the 64 DP of padding to but we don't see any black that we drew inside of that that's because the red pane
is covering it and there are no spacers when there's just one pane in a medium window we see two panes again we have 64 DP of gray padding but now there's a black rectangle where the spacer is this is the space between the panes that we specified in the directive for horizontal partition spacer size and in an expanded window we see all three panes side by side now there are two spacers since there is one between each pair of panes as you can see list detail pane scaffold is very flexible but what if you want
to create an entirely custom adaptive layout we used the current window adaptive info function previously but there are two related functions that you can use as building blocks for much more complex Behavior current window size gives you an in size representing well the current window size in pixels and collect folding features as state gives you a list of folding features we'll cover this in a moment but let's start with the current window size to demonstrate this in a simple way we need to create a function that can take an in size and return a color
just to demonstrate this visually we're going to Define some Maximum Dimensions to use for our calculations to figure out the red color channel will divide the width by Max width The Wider the past in in size the more red up until a Max size of 1,000 since the width could be even wider we coers this value to be no bigger than one we do something similar for green but we use the height instead for blue we actually use the total area so we multiply both dimensions together finally we create and return the new color object
it's not a fancy function but it will give us a color to play around with now we can create a new composable where we use current window size and pass the size into our get color for size function then we can create a box to fill our window and set the background color within the Box we add a column with a white background so we can display some info for the column for now we'll just call two string on the size and display it in a text composable so we can easily see how this value
changes the code is simple but it should be enough to demonstrate the current window size function the window starts out at 220 by 220 with a brownish color resizing it vertically gives us more green and a little more blue resizing it horizontally gives us more and more red until we hit 1000 which was the max size we set after 1,000 the red stays the same but we get a little more blue we can further resize to see other changes but it's important to recognize this means your Android app can be in a window of any
arbitrary size including one that changes dramatically at runtime don't think of a window as a fixed space so that was a very basic use of current window size but what about collect folding features as state we can make a new composable that just Loops over the values returned by collect folding features as state and displays them in a text this is very basic but it will let us demonstrate something important in the column of the previous colorful composable we can call our new folding features demo composable we end up with a white background since both
dimensions are huge but we can also see the hardware folding feature notice that it says the state is flat as we slow slowly fold the device together it switches to half opened fully opening it returns it to Flat we can also pull up from the bottom of the screen and go into split screen mode suddenly the folding info disappears if we resize the window it reappears because your window only needs to know about the hinge if your window goes over the hinge these are some very basic demonstrations of these apis but you can use them
in different ways within your app for example if the folding feature state is half opened and the folding feature orientation is horizontal you can customize your UI for the tabletop posture we've talked about material three adaptive libraries including navigation site scaffold Leist detail pen scaffold supporting pen scaffold and all the advanced apis all of these apis are now available in beta so see how you can use them in your app today to read additional documentation about these apis please see the developer documentation at d android.com compos adaptive if you want a deeper dive on window
side classes in adaptive UI fundamentals please check out the talk building adaptive Android apps by Alex infut and if you want to learn more about this from the designer point of view please see the talk designing adaptive apps by Anisha and Javier I have a really big tablet and two things bother me when using it apps that lock to Portrait why and apps that show a navigation bar that my thumbs can't reach consider using a navigation Suite scaffold in your app today my thumbs will thank you [Applause]