{"id":183,"date":"2020-03-26T12:22:30","date_gmt":"2020-03-26T19:22:30","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=183"},"modified":"2020-04-09T11:49:45","modified_gmt":"2020-04-09T18:49:45","slug":"introducing-dual-screen-layouts-android","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/introducing-dual-screen-layouts-android\/","title":{"rendered":"Introducing dual-screen layouts for Android"},"content":{"rendered":"<p>Hello Android dual-screen developers!<\/p>\n<p>Today we are releasing a preview of our first dual-screen layout control for Java and Kotlin developers. The new control and associated helpers will enable you to build dynamic and responsive apps that take advantage of the Microsoft Surface Duo and its two screens.<\/p>\n<h2>New SDK features<\/h2>\n<p>Today&#8217;s release includes three elements that build upon the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/api-reference\/display-mask\">display mask<\/a> and other APIs:<\/p>\n<ul>\n<li><strong>SurfaceDuoLayout<\/strong> \u2013 a control that helps manage single-screen and dual-screen layouts in a flexible way.<\/li>\n<li><strong>SurfaceDuoScreenManager <\/strong>\u2013 used to subscribe to screen mode changes and have your app respond accordingly.<\/li>\n<li><strong>ScreenHelper <\/strong>\u2013 provides information about the screen and hinge to help you position elements in your UI.<\/li>\n<\/ul>\n<p>This post explains one of many ways to take advantage of these new features, you can learn more in the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-layout\">SurfaceDuoLayout documentation<\/a>.<\/p>\n<h2>Add to your project<\/h2>\n<p>To try out these features, first update your Android Studio project:<\/p>\n<ol>\n<li>In the top-level <b>build.gradle<\/b> file, add these lines inside the <code>allprojects { repositories {<\/code> section:\n<pre class=\"prettyprint\">maven {\r\n    url 'https:\/\/pkgs.dev.azure.com\/MicrosoftDeviceSDK\/DuoSDK-Public\/_packaging\/Duo-SDK-Feed\/maven\/v1'\r\n}\r\n<\/pre>\n<\/li>\n<li>In your module-level <b>build.gradle<\/b> file, add this line in the <code>dependencies {<\/code> section:\n<pre class=\"prettyprint\">implementation 'com.microsoft.device:dualscreen-layout:0.9.0'<\/pre>\n<\/li>\n<li>Java projects should also add this line to their <b>build.gradle<\/b> dependencies, because the library is built with Kotlin:\n<pre class=\"prettyprint\">implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"<\/pre>\n<\/li>\n<li>Initialize a <code>SurfaceDuoScreenManager<\/code> instance in your <code>Application<\/code> class so you can react to access device statues in your code:\n<pre class=\"prettyprint\">SurfaceDuoScreenManager surfaceDuoScreenManager;\r\n\r\n@Override\r\npublic void onCreate() {\r\n    super.onCreate();\r\n    surfaceDuoScreenManager = SurfaceDuoScreenManager.init(this);\r\n}\r\n\r\npublic SurfaceDuoScreenManager getSurfaceDuoScreenManager() {\r\n    return surfaceDuoScreenManager;\r\n}<\/pre>\n<p><code>getSurfaceDuroScreenManager<\/code> will be used in your activities to configure listeners for device mode changes.\n<\/li>\n<\/ol>\n<h2>Using SurfaceDuoLayout<\/h2>\n<p>You can implement dual-screen behavior both using layouts or by listening for screen change events and manipulating fragments, or a combination of the two approaches.<\/p>\n<p>It&#8217;s possible to create a sophisticated, responsive UI declaratively, as shown in the CompanionPaneLevel2 sample (<a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\/tree\/master\/CompanionPaneLevel2\">Java<\/a>, <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples-kotlin\/tree\/master\/CompanionPaneLevel2\">Kotlin<\/a>). In the sample, the main activity contains the following XML layout:<\/p>\n<pre class=\"prettyprint\"><com.microsoft.device.surfaceduo.display.SurfaceDuoLayout\r\n    xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    app:single_screen_layout_id=\"@layout\/single_screen_layout\"\r\n    app:dual_screen_start_layout_id=\"@layout\/picture_dual_screen\"\r\n    app:dual_screen_end_layout_id=\"@layout\/tools_dual_screen\" \/><\/pre>\n<p>It uses the SurfaceDuoLayout and sets three attributes to define the single- and dual-screen behavior:<\/p>\n<ul>\n<li><code>single_screen_layout_id<\/code> \u2013 layout to load in single screen mode, or on other devices.<\/li>\n<li><code>dual_screen_start_layout_id<\/code> \u2013 layout for the left-side screen.<\/li>\n<li><code>dual_screen_end_layout_id<\/code> \u2013 layout for the right-side screen.<\/li>\n<\/ul>\n<p>Each of those layouts can be further specialized (if required) with landscape and portrait versions, as shown in this screenshot:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-layout-tree.png\" alt=\"Layout XML file tree\" width=\"372\" height=\"276\" class=\"alignnone size-full wp-image-190\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-layout-tree.png 372w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-layout-tree-300x223.png 300w\" sizes=\"(max-width: 372px) 100vw, 372px\" \/><\/p>\n<p>Figure 1: Layout resource definitions<\/p>\n<p>You create\/edit these layouts as you normally would in Android Studio:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-android-studio.png\" alt=\"Android Studio layout design surface\" width=\"754\" height=\"508\" class=\"alignnone size-full wp-image-191\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-android-studio.png 754w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/03\/companion-android-studio-300x202.png 300w\" sizes=\"(max-width: 754px) 100vw, 754px\" \/><\/p>\n<p>Figure 2: Android Studio layout editor<\/p>\n<p>Here are some screenshots of the CompanionPaneLevel2 sample app in different modes:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/04\/emulator-4x4-800.png\" alt=\"Portrait and landscape device screenshots\" width=\"800\" height=\"646\" class=\"alignnone size-full wp-image-240\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/04\/emulator-4x4-800.png 800w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/04\/emulator-4x4-800-300x242.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2020\/04\/emulator-4x4-800-768x620.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/p>\n<p>Figure 3: Single-screen and dual-screen layouts using SurfaceDuoLayout<\/p>\n<h3>SurfaceDuoScreenManager<\/h3>\n<p>To use the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-layout#surfaceduoscreenmanager\"><code>SurfaceDuoScreenManager<\/code><\/a>, add a listener in your application or activity where you can react to screen state changes, as shown in this code snippet:<\/p>\n<pre class=\"prettyprint\">\r\n@Override\r\nprotected void onCreate(@Nullable Bundle savedInstanceState) {\r\n    super.onCreate(savedInstanceState);\r\n    setContentView(R.layout.activity_main);\r\n\r\n    ((CompanionPaneApp) getApplication()).getSurfaceDuoScreenManager()\r\n        .addScreenModeListener(new ScreenModeListener() {\r\n\r\n            @Override\r\n            public void onSwitchToSingleScreenMode() {\r\n               \/\/ TODO: Add single-screen behavior\r\n            }\r\n\r\n            @Override\r\n            public void onSwitchToDualScreenMode() {\r\n                \/\/ TODO: Add dual-screen behavior\r\n            }\r\n\r\n        });\r\n}<\/pre>\n<p>You might add code to update views in the activity (like the CompanionPane sample for <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\/tree\/master\/CompanionPaneLevel2\">Java<\/a> &#038; <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\/tree\/master\/CompanionPaneLevel2\">Kotlin<\/a>), or use fragment manager to adjust the UI (like the MasterDetail sample for <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples\/tree\/master\/MasterDetail\">Java<\/a> &#038; <a href=\"https:\/\/github.com\/microsoft\/surface-duo-sdk-samples-kotlin\/tree\/master\/MasterDetail\">Kotlin<\/a>).<\/p>\n<h3>ScreenHelper<\/h3>\n<p>The <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-layout#screenhelper\"><code>ScreenHelper<\/code><\/a> provides information about the device, to help your code understand the device state. There are four static functions:<\/p>\n<ul>\n<li><strong>getHinge<\/strong> \u2013 returns the co-ordinates of the seam where the device&#8217;s hinge fits between the two displays.<\/li>\n<li><strong>getScreenRectangles<\/strong> \u2013 when the device is spanned, returns two rectangles representing the dimensions of the screens.<\/li>\n<li><strong>isDualMode<\/strong> \u2013 whether the application is spanned or not.<\/li>\n<li><strong>getCurrentRotation<\/strong> \u2013 returns the device rotation (0, 90, 180, or 270 degrees).<\/li>\n<\/ul>\n<p>These functions can be used in conjunction with the <code>ScreenManager<\/code> to reason about the device state and render the appropriate UI.<\/p>\n<h2>Resources and feedback<\/h2>\n<p>Refer to the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/api-reference\/dualscreen-layout\">SurfaceDuoLayout documentation<\/a> for more detailed explanations of the alternative approaches for using the SurfaceDuoLayout control. Cross-platform developers using Xamarin should refer to the previous post on <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/bring-your-xamarin-apps-to-surface-duo\/\">bringing Xamarin apps to Surface Duo<\/a>.<\/p>\n<p>We would love to hear from you about your experiences using the SDK, emulator, and your thoughts on how you can utilize these in your apps.<\/p>\n<p>Please reach out using our <a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a> or message me on <a href=\"https:\/\/twitter.com\/conceptdev\">Twitter<\/a> or <a href=\"https:\/\/github.com\/conceptdev\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we are releasing a preview of our first Android dual-screen layout control for Java and Kotlin developers. The new control and associated helpers will enable you to build dynamic and responsive apps that take advantage of the Microsoft Surface Duo and its two screens. We look forward to see what you create with it!<\/p>\n","protected":false},"author":570,"featured_media":253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[31,46,45],"class_list":["post-183","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-dual-screen-development","tag-surface-duo","tag-surface-duo-sdk"],"acf":[],"blog_post_summary":"<p>Today we are releasing a preview of our first Android dual-screen layout control for Java and Kotlin developers. The new control and associated helpers will enable you to build dynamic and responsive apps that take advantage of the Microsoft Surface Duo and its two screens. We look forward to see what you create with it!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/183","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\/570"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=183"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/183\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=183"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}