{"id":2123,"date":"2022-01-13T11:00:12","date_gmt":"2022-01-13T19:00:12","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=2123"},"modified":"2022-01-14T11:02:57","modified_gmt":"2022-01-14T19:02:57","slug":"jetpack-window-manager-release-candidate","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/jetpack-window-manager-release-candidate\/","title":{"rendered":"Jetpack Window Manager release candidate"},"content":{"rendered":"<p>\n  Hello Android developers!\n<\/p>\n<p>\n  Google recently updated a number of dual-screen and foldable packages \u2013<a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/window\">Window Manager<\/a>, <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/slidingpanelayout\">SlidingPaneLayout<\/a>, <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/navigation\">Navigation<\/a>, and <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/preference\">Preference<\/a> \u2013 to release candidate. These components can be used to create unique user experiences on the Microsoft Surface Duo and other foldable devices.\n<\/p>\n<h2>Jetpack Window Manager<\/h2>\n<p>\n  The <a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/window\/layout\/WindowInfoTracker\"><strong>WindowInfoTracker<\/strong><\/a> class provides an API for your app to respond each time the layout changes and is affected by a hinge or fold. There are a number of examples in the <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\">Window Manager samples repo<\/a> which use the library as shown here:\n<\/p>\n<ol>\n<li>\n  Add the package in your build.gradle file:<\/p>\n<pre>implementation 'androidx.window:window:1.0.0-rc01<\/pre>\n<\/li>\n<li>\n  Get an instance of <strong>WindowInfoTracker<\/strong> and then use a\u00a0lifecycleScope\u00a0to collect an updated\u00a0<strong>WindowLayoutInfo<\/strong>\u00a0and make changes to the user interface accordingly:<\/p>\n<pre>override fun onCreate(savedInstanceState: Bundle?) {\r\n    super.onCreate(savedInstanceState)\r\n\r\n    lifecycleScope.launch(Dispatchers.Main) {\r\n          lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {\r\n            WindowInfoTracker.getOrCreate(this@MainActivity)\r\n\t\t   .windowLayoutInfo\r\n            .collect { newLayoutInfo ->\r\n              for (displayFeature : DisplayFeature in newLayoutInfo.displayFeatures) {\r\n                  if (displayFeature is FoldingFeature) {\r\n                      \/\/ do something with hinge\/fold\r\n                  }\r\n              }\r\n          }\r\n    }\r\n}<\/pre>\n<\/li>\n<\/ol>\n<h2>Sliding Pane Layout<\/h2>\n<p>\n  See our <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/foldable-slidingpanelayout-preview\/\">earlier blog post<\/a> for details on how SlidingPaneLayout behaves on different devices and postures. To use the latest: \n<\/p>\n<ol>\n<li>\n  Add the package in your build.gradle file:<\/p>\n<pre>implementation 'androidx.slidingpanelayout:slidingpanelayout:1.0.0-rc01<\/pre>\n<\/li>\n<li>\n  Add the layout to your view XML<\/p>\n<pre>&lt;androidx.slidingpanelayout.widget.SlidingPaneLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\nandroid:id=\"@+id\/sliding_pane_layout\"\r\nandroid:layout_width=\"match_parent\"\r\nandroid:layout_height=\"match_parent\">\r\n&lt;!-- first child -->\r\n&lt;!-- second child -->\r\n&lt;\/androidx.slidingpanelayout.widget.SlidingPaneLayout>\r\n<\/pre>\n<p>\n  <img decoding=\"async\" width=\"647\" height=\"483\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/adapting-to-android-multi-window-and-foldable-devi.png\" class=\"wp-image-2124\" alt=\"Adapting to Android multi-window and foldable devices\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/adapting-to-android-multi-window-and-foldable-devi.png 647w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/adapting-to-android-multi-window-and-foldable-devi-300x224.png 300w\" sizes=\"(max-width: 647px) 100vw, 647px\" \/>\n<\/p>\n<h2>Navigation<\/h2>\n<p>\n  Jetpack Navigation component also got a <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/navigation#2.4.0-rc01\">new update (2.4.0-rc01)<\/a> that makes it fold and large-screen aware: the component uses now SlidingPaneLayout internally. Since we already have seen what this component does (just above), it\u2019s easy to see how the Navigation component can benefit of it: we can now navigate from A to B destinations following a list-detail pattern.\n<\/p>\n<p>\n  On single-screen devices, single-screen mode on Surface Duo, or multi-window mode on other foldable devices, we go from A to B destinations showing independent panes at a time (B overlaps A when visible). But on spanned mode on foldables or large-screen devices with more display area, we can now go from A to B destinations showing both at the same time (showing two panes).\n<\/p>\n<p>\n  Follow these steps to add foldable-aware navigation to your project:\n<\/p>\n<ol>\n<li>\n  Add the dependency in your build.gradle file:<\/p>\n<pre>implementation(\"androidx.navigation:navigation-fragment-ktx:2.4.0-rc01\")<\/pre>\n<\/li>\n<li>\n  We have to create a Fragment that extends from <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:navigation\/navigation-fragment\/src\/main\/java\/androidx\/navigation\/fragment\/AbstractListDetailFragment.kt\">AbstractListDetailFragment<\/a> and implement <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:navigation\/navigation-fragment\/src\/main\/java\/androidx\/navigation\/fragment\/AbstractListDetailFragment.kt;drc=f5fbf3227a0d9111f8d284398ad58554429046cb;l=200\">onCreateListPaneView<\/a> to supply custom view for the list pane. Then we provide a custom <a href=\"https:\/\/developer.android.com\/reference\/androidx\/navigation\/fragment\/NavHostFragment\">NavHostFragment<\/a> by overriding <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:navigation\/navigation-fragment\/src\/main\/java\/androidx\/navigation\/fragment\/AbstractListDetailFragment.kt;drc=f5fbf3227a0d9111f8d284398ad58554429046cb;l=210\">onCreateDetailPaneNavHostFragment<\/a> where we indicate the navigation path we want to follow.<\/p>\n<pre>class TwoPaneFragment : AbstractListDetailFragment() {\r\n\r\n    private lateinit var binding: ListPaneBinding\r\n\r\n    override fun onCreateListPaneView(\r\n        inflater: LayoutInflater,\r\n        container: ViewGroup?,\r\n        savedInstanceState: Bundle?\r\n    ): View {\r\n        binding = ListPaneBinding.inflate(inflater, container, false)\r\n        return binding.root\r\n    }\r\n\r\n    override fun onCreateDetailPaneNavHostFragment(): NavHostFragment {\r\n        return NavHostFragment.create(R.navigation.two_pane_navigation)\r\n    }\r\n...\r\n}<\/pre>\n<\/li>\n<\/ol>\n<p>\nFor more information you can have a look at a <a href=\"https:\/\/github.com\/CesarValiente\/navigation-foldable\">sample we have created<\/a> where we showcase an easy-to-follow navigation flow.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"922\" height=\"739\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-8.png\" class=\"wp-image-2125\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-8.png 922w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-8-300x240.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-8-768x616.png 768w\" sizes=\"(max-width: 922px) 100vw, 922px\" \/>\n<\/p>\n<h2>Preference<\/h2>\n<p>\n  Very similar to what Jetpack Navigation component got in its new update, Jetpack Preference is now fold and large-screen aware too. Its <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/preference#1.2.0-rc01\">latest update (1.2.0-rc01)<\/a> uses SlidingPaneLayout internally, and, as you may guess, on foldable and large-screen devices, where there is more display area, preferences are shown in a list-detail manner. Very useful!\n<\/p>\n<p>\n  Follow these steps to add foldable-aware preferences to your project:\n<\/p>\n<ol>\n<li>\n  Add the dependency in your build.gradle file:<\/p>\n<pre>implementation(\"androidx.preference:preference-ktx:1.2.0-rc01\")<\/pre>\n<\/li>\n<li>\n  We have to create a Fragment that extends from <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:preference\/preference\/src\/main\/java\/androidx\/preference\/PreferenceHeaderFragmentCompat.kt\">PreferenceHeaderFragmentCompat<\/a> and implement <a href=\"https:\/\/cs.android.com\/androidx\/platform\/frameworks\/support\/+\/androidx-main:preference\/preference\/src\/main\/java\/androidx\/preference\/PreferenceHeaderFragmentCompat.kt;drc=cbaa25abee598969fe26fb9b394784c95eb38f45;l=203\">onCreatePreferenceHeader<\/a> where we will supply preference headers that will be used as the list pane: <\/p>\n<pre>class TwoPanePreference : PreferenceHeaderFragmentCompat() {\r\n\r\n    override fun onCreatePreferenceHeader(): PreferenceFragmentCompat {\r\n        return MainPreferenceFragment()\r\n    }\r\n}<\/pre>\n<\/li>\n<li>\n<p>\n  We will set them either by calling <a href=\"https:\/\/developer.android.com\/reference\/androidx\/preference\/PreferenceFragmentCompat#setPreferencesFromResource(int,%20java.lang.String)\">setPreferenceFromResource<\/a> or <a href=\"https:\/\/developer.android.com\/reference\/androidx\/preference\/PreferenceFragmentCompat#setPreferenceScreen(androidx.preference.PreferenceScreen)\">setPreferenceScreen<\/a>.\n<\/p>\n<pre>class MainPreferenceFragment : PreferenceFragmentCompat() {\r\n\r\n    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\r\n        setPreferencesFromResource(R.xml.preferences, rootKey)\r\n    }\r\n}<\/pre>\n<\/li>\n<\/ol>\n<p>\n  For more information you can have a look at a <a href=\"https:\/\/github.com\/CesarValiente\/preferences-foldable\">sample we have created<\/a> where we showcase a preference screen scenario that is easy to understand.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"918\" height=\"736\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-9.png\" class=\"wp-image-2126\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-9.png 918w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-9-300x241.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/12\/word-image-9-768x616.png 768w\" sizes=\"(max-width: 918px) 100vw, 918px\" \/>\n<\/p>\n<h2>Resources and feedback <\/h2>\n<p>\n  Check out the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\">Surface Duo developer documentation<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/\">past blog posts<\/a> for links and details on all our samples. You can find our <a href=\"https:\/\/github.com\/microsoft\/surface-duo-window-manager-samples\">Jetpack Window Manager samples<\/a> on GitHub.\n<\/p>\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\">feedback forum<\/a> or message us on Twitter <a href=\"https:\/\/twitter.com\/surfaceduodev\">@surfaceduodev<\/a>.\n<\/p>\n<p>\n  This week the <a href=\"https:\/\/twitch.tv\/surfaceduodev\">Twitch stream<\/a> will be live at the Europe-friendly time of 13:00h CET (12 noon GMT) \u2013 join the team to chat live about this sample app. The stream will be replayed at our usual time of 11am Pacific time for those in the Americas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Android developers! Google recently updated a number of dual-screen and foldable packages \u2013Window Manager, SlidingPaneLayout, Navigation, and Preference \u2013 to release candidate. These components can be used to create unique user experiences on the Microsoft Surface Duo and other foldable devices. Jetpack Window Manager The WindowInfoTracker class provides an API for your app to [&hellip;]<\/p>\n","protected":false},"author":30297,"featured_media":2126,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[705,706,473],"class_list":["post-2123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-java","tag-jetpack-window-manager","tag-kotlin"],"acf":[],"blog_post_summary":"<p>Hello Android developers! Google recently updated a number of dual-screen and foldable packages \u2013Window Manager, SlidingPaneLayout, Navigation, and Preference \u2013 to release candidate. These components can be used to create unique user experiences on the Microsoft Surface Duo and other foldable devices. Jetpack Window Manager The WindowInfoTracker class provides an API for your app to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2123","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\/30297"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=2123"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/2123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/2126"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=2123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=2123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=2123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}