{"id":1608,"date":"2021-06-03T17:05:17","date_gmt":"2021-06-04T00:05:17","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=1608"},"modified":"2021-06-03T17:05:17","modified_gmt":"2021-06-04T00:05:17","slug":"flutter-foldable-hinge-angle","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/flutter-foldable-hinge-angle\/","title":{"rendered":"A new angle on Flutter"},"content":{"rendered":"<p>\n  Hello Flutter developers!\n<\/p>\n<p>\n  Today we are taking a closer look at the hinge on Microsoft Surface Duo and other foldable devices. The hinge holds the two parts of the device together, but it also has a sensor inside which tells us about the angle between the two screens.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"520\" height=\"293\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/surface-duo-hinge-in-action.gif\" class=\"wp-image-1609\" alt=\"Surface Duo hinge in action\" \/><br\/><em>Figure 1: Surface Duo Hinge in action<\/em>\n<\/p>\n<h2>Hinge angle vs device posture<\/h2>\n<p>\n  The hinge angle is already used to calculate the <a href=\"https:\/\/developer.android.com\/guide\/topics\/ui\/foldables#postures\">device posture<\/a>, which is exposed using <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/flutter\/mediaquery\">MediaQuery<\/a>. The MediaQuery update is included in the Flutter foldable support <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/flutter-dual-screen-foldable\/\">we blogged about previously<\/a>, and which is currently in review. For example, the \u201chalf-opened\u201d posture corresponds to hinge angles around 90 degrees. If the posture is enough for your app to provide a better experience, we recommend using it instead of the angle coming from the sensor directly.\n<\/p>\n<p>\n  There are situations where the <strong>hinge angle<\/strong> itself is important for your app. This raw data is not part of MediaQuery, as this would update your whole app too often. It is instead provided as part of the <a href=\"https:\/\/pub.dev\/packages\/dual_screen\">dual_screen<\/a> Flutter plugin.\n<\/p>\n<h2>Hinge angle values<\/h2>\n<p>\n  Surface Duo has a hinge that supports the whole 0 to 360 degrees range of movement. You can develop and test your app using other foldable devices and emulators, but keep in mind they usually have a limited range of movement, either below 180 degrees or above 180 degrees. To make better sense of what these values mean, here are four important example angles:\n<\/p>\n<ul>\n<li>\n    0 &#8211; Screens are facing each other, and not visible. Device is closed.\n  <\/li>\n<li>\n    90 &#8211; Device is an &#8220;L&#8221; shape with the screens on the inside. Posture is \u201chalf-opened\u201d.\n  <\/li>\n<li>\n    180 &#8211; Device is flat. Screens are facing the same direction. Posture is \u201cflat\u201d.\n  <\/li>\n<li>\n    360 &#8211; Screens are facing opposite directions and only one screen is operating. Since only one screen is operating, the device now behaves as a single-screen device and postures are no longer reported in MediaQuery.\n  <\/li>\n<\/ul>\n<h2>Reading the angle in Flutter<\/h2>\n<p>\n  Add <a href=\"https:\/\/pub.dev\/packages\/dual_screen\/install\">dual_screen<\/a> to your pub.dev <code>dependencies<\/code> section.\n<\/p>\n<pre>dependencies:\r\n    dual_screen: ^1.0.0<\/pre>\n<p>\n  Import and use in your dart files.\n<\/p>\n<pre>\r\n  import 'package:dual_screen\/dual_screen_info.dart';\r\n  DualScreenInfo.hingeAngleEvents.listen((double hingeAngle) {\r\n    print(hingeAngle);\r\n  });\r\n  DualScreenInfo.hasHingeAngleSensor.then((bool hasHingeSensor) {\r\n    print(hasHingeSensor);\r\n  });<\/pre>\n<p>\n  You now have access to two new static properties:\n<\/p>\n<ul>\n<li>\n    <code>hingeAngleEvents<\/code> &#8211; Broadcast stream of events from the device hinge angle sensor. If the device is not equipped with a hinge angle sensor, the stream produces no events.\n  <\/li>\n<li>\n    <code>hasHingeAngleSensor<\/code> &#8211; Future returning true if the device has a hinge angle sensor. Alternatively, if your app already uses <code>MediaQuery.displayFeatures<\/code> or <code>MediaQuery.hinge<\/code> to adapt to foldable or dual-screen form factors, you can safely assume the hinge angle sensor exists and that <code>hingeAngleEvents<\/code> produces usable values.\n  <\/li>\n<\/ul>\n<h2>Sample app<\/h2>\n<p>\n  There is a sample app available on the <a href=\"https:\/\/github.com\/microsoft\/flutter-dualscreen\/tree\/main\/example\">dual_screen GitHub page<\/a>. You can test the sample app using the regular foldable emulators available in Android Studio or using the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/emulator\/\">Surface Duo emulator<\/a>. The Surface Duo emulator is the only one with two separate screens.\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1101\" height=\"653\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image.png\" class=\"wp-image-1610\" alt=\"Surface Duo Emulator running the sample app with 149 degrees on the hinge angle\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image.png 1101w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-300x178.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1024x607.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-768x455.png 768w\" sizes=\"(max-width: 1101px) 100vw, 1101px\" \/><br\/><em>Figure 2: Surface Duo Emulator running the sample app with 149 degrees on the hinge angle<\/em>\n<\/p>\n<p>\n  <img decoding=\"async\" width=\"1101\" height=\"862\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1.png\" class=\"wp-image-1611\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1.png 1101w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1-300x235.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1-1024x802.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/06\/word-image-1-768x601.png 768w\" sizes=\"(max-width: 1101px) 100vw, 1101px\" \/><br\/><em>Figure 3: Android Studio Emulator running the sample app with 187 degrees on the hinge angle<\/em>\n<\/p>\n<h2>Feedback and resources<\/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\/tag\/flutter\/\">past Flutter blog posts<\/a> for links and details on all our samples. You can find our Flutter samples 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<h2>Links<\/h2>\n<ul>\n<li><a href=\"https:\/\/pub.dev\/packages\/dual_screen\">pub.dev dual_screen plugin<\/a>\n  <\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/dual-screen\/flutter\/hinge-angle\">Flutter hinge angle documentation<\/a>\n  <\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/flutter-dualscreen\">Source code of the dual_screen plugin<\/a>\n  <\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/flutter-dualscreen\/tree\/main\/example\">Sample app on GitHub<\/a>\n  <\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Hello Flutter developers! Today we are taking a closer look at the hinge on Microsoft Surface Duo and other foldable devices. The hinge holds the two parts of the device together, but it also has a sensor inside which tells us about the angle between the two screens. Figure 1: Surface Duo Hinge in action [&hellip;]<\/p>\n","protected":false},"author":54297,"featured_media":1609,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[712,693,46],"class_list":["post-1608","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-dart","tag-flutter","tag-surface-duo"],"acf":[],"blog_post_summary":"<p>Hello Flutter developers! Today we are taking a closer look at the hinge on Microsoft Surface Duo and other foldable devices. The hinge holds the two parts of the device together, but it also has a sensor inside which tells us about the angle between the two screens. Figure 1: Surface Duo Hinge in action [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1608","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\/54297"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=1608"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1608\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/1609"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=1608"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=1608"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=1608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}