Surface DUO is the most exciting device I’ve seen in years. Built by Microsoft, it will run Android on a dual-screen setup which allows for apps to run side by side or extended, using both screens.
小号 urface DUO是我多年来看到的最令人兴奋的设备。 它由Microsoft构建,将在双屏设置上运行Android,该设置允许应用同时在两个屏幕上并排运行或扩展运行。
In this article, I want to take a look at what do we need to build a Master/Detail app for dual-screen devices.
在本文中,我想看看为双屏设备构建Master / Detail应用程序需要做什么。
To prepare the post, I’ve rewritten from scratch this Master/Detail sample provided by Microsoft to help me better understand the Surface Duo and to:
为了准备该帖子,我从头开始重写了Microsoft提供的该Master / Detail示例,以帮助我更好地了解Surface Duo,并:
- Reduce the number of fragments used in the sample and (hopefully) make it easier to understand. 减少样品中使用的碎片数量,并(希望)使其更易于理解。
Explore how
ViewModel
&LiveData
can be used in dual-screen setups.探索如何在双屏设置中使用
ViewModel
和LiveData
。- Add support for Portrait Dual Mode, which the original sample didn’t have. 添加对肖像双模式的支持,而原始示例则没有。
Here’s a link to the repository if you rather jump directly into the code:
如果您直接跳转到代码中,这是到存储库的链接:
注意铰链 (Mind the hinge)

A dual-screen device is more than a tablet, we can’t just rely on the app’s landscape layouts to provide the best experience for our users.
双屏设备不仅仅是平板电脑,我们不能仅仅依靠应用程序的横向布局为用户提供最佳体验。
The hinge has a visual and conceptual impact. Having that separation in the middle of the screen forces us to organise our content differently. Our landscape layouts can’t just be a wider portrait with the content aligned in the middle, otherwise, the hinge will cover part of it:
铰链具有视觉和概念上的影响 。 屏幕中间的分隔迫使我们以不同的方式组织内容。 我们的景观布局不能只是将内容对齐在中间的宽阔肖像,否则,铰链将覆盖其中的一部分:

We need to design our layouts having the hinge in mind. We’ll see that there are functions in the Surface Duo SDK to detect if there’s a hinge and where.
我们需要在设计布局时考虑到铰链。 我们将看到Surface Duo SDK中提供了一些功能来检测是否有铰链以及在何处。
There’s also the conceptual implications. Arranging content around the hinge is not enough. Its presence makes a clear separation between both screens and the user will expect the content on them to have different responsibilities. In this case, we’ll explore the Master/Detail concept but there are many more options: Two pages, Companion, Dual view, etc.
还有概念上的含义。 仅在铰链周围布置内容是不够的。 它的存在使两个屏幕之间清晰地分开,并且用户希望它们上的内容具有不同的职责。 在这种情况下,我们将探讨“主/详细”概念,但还有更多选项 :两页,同伴,双重视图等。
掌握/细节:我们需要什么 (Master/Detail: what we need)

A Surface Duo device can be in either portrait or landscape and for each one of those rotations our app can be displayed in single mode or dual mode. That’s four options but, as we’ll see, only three different layouts will be needed to cover all of them.
Surface Duo设备可以是纵向或横向模式,对于这些旋转中的每一个旋转,我们的应用程序都可以单模式或双模式显示。 这是四个选项,但是,正如我们将看到的那样,将只需要三个不同的布局即可覆盖所有这些。
What we need:
我们需要的:
ListFragment
to display the list ofItem
ListFragment
显示Item
列表DetailsFragment
to display one simpleItem
显示一个简单
Item
DetailsFragment
MainActivity
to hold both fragments (either in Single Mode or Dual Mode)MainActivity
可以容纳两个片段(在单模式或双模式下)MainViewModel
to hold the view logic and serve as a communication bridge between fragmentsMainViewModel
保留视图逻辑并充当片段之间的通信桥梁






双模式是棘手的位。 (Dual Mode is the tricky bit.)
In Single Mode, we only need to display one fragment at a time, but in Dual Mode our app needs to display both ListFragment
and DetailsFragment
together.Here’s when things become interesting. Single Mode only cares about one screen, so for both portrait and landscape we can get away with just one layout if we design it to work well in both orientations. But Dual Mode in portrait needs to arrange things from top to bottom and, in landscape, from left to right. This means we need three different layouts for MainActivity
:
在单模式下,我们一次只需要显示一个片段,但是在双模式下,我们的应用程序需要同时显示ListFragment
和DetailsFragment
。 “单模式”只关心一个屏幕,因此对于纵向和横向而言,如果我们将其设计为在两种方向都可以正常工作,则可以仅采用一种布局。 但是,肖像双模式需要从上到下,从横向到从左到右排列事物。 这意味着MainActivity
需要三种不同的布局 :
Layout 1: Single Mode. This is the one we’re used to, with space for one single fragment and used both in portrait and landscape
布局1:单模式 。 这是我们习惯使用的空间,只有一个片段的空间,同时用于纵向和横向
Layout 2: Dual Mode Portrait: With space for two fragments and a gap for the hinge, organised vertically
布局2:双模式人像 : 垂直排列 ,有两个碎片的空间和铰链的间隙
Layout 3: Dual Mode Landscape: With space for two fragments and a gap for the hinge, organised horizontally
布局3:双模式景观 :随着对两个片段的空间和用于铰链的间隙,组织水平



以编程方式设置布局 (Setting layouts programmatically)
Every time there’s a configuration change in our app we need to decide which one of those three layouts needs to be set.
每当我们的应用程序中发生配置更改时,我们都需要确定需要设置这三种布局中的哪一种。
Layouts 2 and 3 are the same layout in a different orientation so we can rely on Android’s native resource by orientation support for this.
布局2和布局3是相同的布局,但方向不同,因此我们可以通过方向支持来依靠Android的本机资源。

In our ActivityonConfigurationChange
we can have something like this:
在我们的活动onConfigurationChange
我们可以像这样:
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val layoutId = when {
isDuoDeviceInDualMode() -> R.layout.main_activity_dual_modeelse -> R.layout.main_activity_single_mode}
setContentView(layoutId)
}
Android will take care of orientation resource provisioning, giving us the correct R.layout.main_activity_dual_mode
layout for portrait or landscape.
Android将负责定向资源的配置,为我们提供纵向或横向的正确R.layout.main_activity_dual_mode
布局。
Once we have the correct layout set, it’s a matter of displaying the correct fragment (or fragments) in the correct buckets.
一旦我们设置了正确的布局,就可以在正确的存储桶中显示正确的片段。

Surface DUO SDK (Surface DUO SDK)
The Duo SDK is not required to build an app able to run in the Surface Duo, but it provides some utilities to make the experience better for the user.
不需要Duo SDK来构建能够在Surface Duo上运行的应用程序,但是它提供了一些实用程序,可以为用户带来更好的体验。
该应用程序是否在Surface Duo设备中运行? (Is the app running in a Surface Duo Device?)
DisplayMask: Represents the area of the display that is not functional for displaying content.
DisplayMask :表示显示器上不能用于显示内容的区域。
If we can create a DisplayMask
then the app is running in a Duo Device. We can use this snippet to determine whether our app is running on a Duo Device. We should check this before setting the activity layout.
如果我们可以创建DisplayMask
则该应用程序将在Duo设备中运行。 我们可以使用此代码段确定我们的应用程序是否在Duo设备上运行。 在设置活动布局之前,我们应该检查一下。
fun isDuoDevice(context: Context): Boolean {
return try {DisplayMask.fromResourcesRectApproximation(context) != null
} catch (ex: Exception) {
false
}
}
单模还是双模? (Single or Dual Mode?)
DisplayMask.getBoundingRectsForRotation(int rotation)
Returns a list of Rects with respect to the rotation, each of which is the bounding rectangle for a non-functional area on the display.
DisplayMask.getBoundingRectsForRotation(int rotation)
返回相对于旋转的Rect列表,每个列表都是显示器上非功能区域的边界矩形。
An app is in Dual Mode when it’s presented across both screens. In that case, the hinge will intersect our app window. We can use DisplayMask.getBoundingRectsForRotation()
to obtain the hinge Rect
and check if it intersects our app window’s Rect
在两个屏幕上同时显示的应用程序处于双模式。 在这种情况下,铰链将与我们的应用程序窗口相交。 我们可以使用DisplayMask.getBoundingRectsForRotation()
获取铰链Rect
并检查它是否与我们应用窗口的Rect
相交
fun isDualMode(): Boolean {
val hinge: Rect = getHinge(rotation)
val windowRect: Rect = getWindowRect()
if (windowRect.width() > 0 && windowRect.height() > 0) {
return hinge.intersect(windowRect)
} else {
return false
}
}private fun getHinge(rotation: Int): Rect {
return displayMask
.getBoundingRectsForRotation(rotation)
.let { boundings -> boundings[0] }}
更多资源 (More resources)
Official documentation: https://aka.ms/SurfaceDuoSDK-Docs
官方文档: https : //aka.ms/SurfaceDuoSDK-Docs
Surface DUO SDK Feedback forum: https://aka.ms/SurfaceDuoSDK-Feedback
Surface DUO SDK反馈论坛: https : //aka.ms/SurfaceDuoSDK-Feedback
Surface DUO blog: https://aka.ms/SurfaceDuoSDK-Blog
Surface DUO博客: https : //aka.ms/SurfaceDuoSDK-Blog
Some interesting talks about building Android apps for Dual-screen devices https://developer.microsoft.com/en-us/microsoft-365/virtual-events
关于为双屏设备构建Android应用程序的一些有趣的演讲https://developer.microsoft.com/zh-cn/microsoft-365/virtual-events
This is only a quick look at what the Surface Duo can offer. I’m looking forward to being able to experiment further with the SDK and excited to find out what new experiences will dual-screen devices bring to the Android ecosystem. Ping me on Twitter if you want to chat more about it, I’d love to hear your thoughts!
这只是对Surface Duo可以提供的功能的快速浏览。 我期待能够进一步试验SDK,并很高兴发现双屏设备将为Android生态系统带来哪些新体验。 如果您想在Twitter上与我聊天,请与我联系,我很想听听您的想法!
Thanks to Cesar Valiente and pablisco for their feedback and help on this post 🙌
感谢Cesar Valiente和pablisco对本文的反馈和帮助🙌
翻译自: https://medium.com/swlh/surface-duo-how-dual-screen-devices-work-in-practice-5b8057b88376