{"id":2814,"date":"2022-10-13T11:16:30","date_gmt":"2022-10-13T18:16:30","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=2814"},"modified":"2022-10-14T08:52:52","modified_gmt":"2022-10-14T15:52:52","slug":"foldable-navigation-rail","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/foldable-navigation-rail\/","title":{"rendered":"Foldable Navigation Rail"},"content":{"rendered":"<p>\n  Hello Android developers!\n<\/p>\n<p>\n  This week we\u2019re excited to share with you a new library to make it easy to support Navigation Rail on foldable devices like Surface Duo.\n<\/p>\n<h2>Navigation Rail package<\/h2>\n<p>\n  One of the tricks when building mobile apps for Surface Duo devices is to avoid your UI being obscured by the hinge. Controls that aren\u2019t aware of foldable devices may place elements \u201cunder\u201d the fold area, making them hard to read and touch:\n<\/p>\n<p>\n  <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/word-image-2814-1.png\" class=\"wp-image-2815\" width=\"250\" height=\"400\" alt=\"Surface Duo showing Navigation Rail sample\" \/>\n<\/p>\n<p>\n  To avoid this typically requires custom code using the <code>WindowInfoTracker<\/code> from the Jetpack Window Manager, observing changes to the <code>WindowLayoutInfo<\/code>, and adjusting the layout accordingly.\n<\/p>\n<p>\n  To make things easier, the <a href=\"https:\/\/learn.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-library\/\">Dual-screen layout library<\/a> contains a collection of components designed to automatically adapt to foldable devices, so no additional code is required. \n<\/p>\n<h2>Adding the NavigationRailView<\/h2>\n<p>\n  Similar to the <a href=\"https:\/\/learn.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-library\/bottomnavigation\/surfaceduo-bottomnavigationview\">BottomNavigationView<\/a> and the <a href=\"https:\/\/learn.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-library\/tabs\/surfaceduo-tablayout\">TabLayout<\/a>, this component is a customized <a href=\"https:\/\/developer.android.com\/reference\/com\/google\/android\/material\/navigationrail\/NavigationRailView\">NavigationRailView<\/a> from Google\u2019s Material library. It is designed to display its child views in a way that will not interfere with the hinge found on foldable devices like Surface Duo.\n<\/p>\n<p>\n  The NavigationRailView can use the <code>setMenuGravity()<\/code> function to control how the destinations from the menu views will be grouped: <code>Top<\/code>, <code>Center<\/code>, or <code>Bottom<\/code>. \n  <br \/>\n  The view encapsulates an implementation of the <code>WindowInfoTracker<\/code> and for each of the above three cases it will try to reposition some of the buttons to avoid overlapping with the folding feature.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1200\" height=\"496\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/inserting-image-.png\" class=\"wp-image-2816\"  alt=\"Surface Duo showing Navigation Rail sample\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/inserting-image-.png 1200w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/inserting-image--300x124.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/inserting-image--1024x423.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/inserting-image--768x317.png 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/>\n<\/p>\n<p>\n  This can be accomplished either using the xml\u2019s <code>app:menuGravity<\/code> attribute or using the <code>setMenuGravity()<\/code> Java function: \n<\/p>\n<pre>\r\n  app:menuGravity=\"top\"\r\n<\/pre>\n<p>\n  or Kotlin setter function:\n<\/p>\n<pre>\r\n  binding.navRailView.menuGravity = Gravity.TOP\r\n<\/pre>\n<p>\n  A special case is if we want to position the button in the center. Here we have an extra option in the form of a function called <code>arrangeButtons(startBtnCount, endBtnCount)<\/code> that takes two parameters: <code>startBtnCount<\/code> telling how many buttons should be positioned on the top screen and <code>endBtnCount<\/code> telling how many buttons should be positioned on the bottom screen, respectively. \n<\/p>\n<p>\n  This example shows how to set the first five destinations on the top screen and last two on the bottom screen:\n<\/p>\n<pre>\r\n  binding.navRailView.arrangeButtons(5,2)\r\n<\/pre>\n<p>\n  <img decoding=\"async\" width=\"392\" height=\"496\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/word-image-2814-3.png\" class=\"wp-image-2817\" alt=\"Surface Duo showing Navigation Rail sample\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/word-image-2814-3.png 392w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2022\/10\/word-image-2814-3-237x300.png 237w\" sizes=\"(max-width: 392px) 100vw, 392px\" \/>\n<\/p>\n<h2>Animations and gestures<\/h2>\n<p>\n  Keeping the tradition with other components, NavigationRailView also supports animations and fling gestures.\n<\/p>\n<p>\n  The position of the destinations can also be changed at runtime using the two methods described above. To make the transition more pleasant, a translation animation can be used. This option can be enabled or disabled by changing the <code>useAnimation<\/code> property from both xml and Java or Kotlin. By default, the value is set to true.\n<\/p>\n<p>\n  In addition to this, we can also set up a custom interpolator for the animation using the <code>animationInterpolator<\/code> property: \n<\/p>\n<pre>\r\n  binding.navRailView.animationInterpolator = AccelerateInterpolator()\r\n<\/pre>\n<p>\n  By default, an instance of the <code>AccelerateDecelerateInterpolator()<\/code> is used.\n<\/p>\n<h2>Gestures<\/h2>\n<p>\n  The button\u2019s position can also be changed at runtime using a swipe gesture on the component.\n<\/p>\n<p>\n  The component can detect a swipe up or down gesture and will change the gravity of the destinations to <code>Gravity.TOP<\/code> or <code>Gravity.BOTTOM<\/code>.\n<\/p>\n<p>\n  This feature can be turned on or off by using the <code>allowFlingGesture<\/code>. By default, it is set to true.\n<\/p>\n<h2>Resources and feedback<\/h2>\n<p>\n  If you have any questions, or would like to tell us about your apps, use the <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\" target=\"_blank\" rel=\"noopener\">feedback forum<\/a> or message us on Twitter <a href=\"https:\/\/twitter.com\/surfaceduodev\" target=\"_blank\" rel=\"noopener\">@surfaceduodev<\/a>.\u00a0\n<\/p>\n<p>\n  Finally, join us live on Twitch on Friday at 11am (Pacific Time) to discuss the Navigation Rail, foldable user experiences, and any other Surface Duo developer questions you might have.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Android developers! This week we\u2019re excited to share with you a new library to make it easy to support Navigation Rail on foldable devices like Surface Duo. Navigation Rail package One of the tricks when building mobile apps for Surface Duo devices is to avoid your UI being obscured by the hinge. Controls that [&hellip;]<\/p>\n","protected":false},"author":82638,"featured_media":2816,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2814","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk"],"acf":[],"blog_post_summary":"<p>Hello Android developers! This week we\u2019re excited to share with you a new library to make it easy to support Navigation Rail on foldable devices like Surface Duo. Navigation Rail package One of the tricks when building mobile apps for Surface Duo devices is to avoid your UI being obscured by the hinge. Controls that [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/82638"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=2814"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2814\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/2816"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=2814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=2814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=2814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}