New dual-screen controls preview

Cristian Verdes

Cristian

Hello Microsoft Surface Duo Android developers!

This week we’ve updated and refactored our controls to help you build dual-screen applications with less work and more functionality.

The classes in the previous release of our library are still available:

  • ScreenHelper
  • SurfaceDuoScreenManager
  • SurfaceDuoLayout

However, we have re-packaged the controls into separate libraries so they’re easier to add only what you need:

  • Core – contains ScreenHelper and SurfaceDuoScreenManager. You can use these directly in your code and are also used by the other libraries.
  • Bottom navigation – extends the bottom navigation control to fit into one or two screens.
  • Fragment handler – contains a helper class to manage fragments on one or two screens.
  • Layouts – contains our original SurfaceDuoLayout control, as well as a simpler “helper layout” that will shift a view to the left or right.
  • Tabs – extends the tab layout so that the tabs can be positioned across one or two screens.

Each of the new controls are described below and you can refer to the updated documentation for more information. You can add them to your project by updating your gradle dependencies according to these instructions. Samples for each are available alongside the open-source code. Use our feedback forum or the SDK issues list to provide feedback on these controls and let us know what else you’d like to see added.

Screen helper

This helper class provides functions to query the state of the device, such as the hinge area, the screen rectangles when the app is spanned, and whether the app is spanned. Here’s one example using the screen helper in the code snippet below that demonstrates how to show or hide a control depending on spanned state:

val visibility = if (ScreenHelper.isDeviceSurfaceDuo(this) &&
    ScreenHelper.isDualMode(this)
) { // isSpanned on a Surface Duo
    View.VISIBLE
} else {
    View.GONE
}

Surface Duo screen manager

The screen manager can be wired up to listen for changes in the app’s state so that your code can respond to events like spanning or unspanning and change the layout accordingly. This code shows a simple example of responding to an application changing from one screen to two (or vice versa):

// Application subclass
lateinit var surfaceDuoScreenManager: SurfaceDuoScreenManager
override fun onCreate() {
    super.onCreate()
    surfaceDuoScreenManager = SurfaceDuoScreenManager.getInstance(this)
}

// Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    (application as SampleApp).surfaceDuoScreenManager.addScreenModeListener(
        this,
        object : ScreenModeListener {
            override fun onSwitchToSingleScreen() {
                Toast.makeText(
                    this@MainActivity,
                    "Single Screen Mode",
                    Toast.LENGTH_SHORT
                ).show()
            }
            override fun onSwitchToDualScreen() {
                Toast.makeText(
                    this@MainActivity,
                    "Dual Screen Mode",
                    Toast.LENGTH_SHORT
                ).show()
            }
        }
    )
}

Bottom navigation

The default behavior for bottom navigation in a dual-screen view could result in one of the options being obscured by the hinge. The Surface Duo bottom navigation has configuration controls to choose which screen to group the navigation options:

  • DisplayPosition.START – grouped on first screen.
  • DisplayPosition.END – grouped on second screen.
  • DisplayPosition.DUAL – spanned across both screens (might appear under hinge).

Surface Duo emulator showing bottom navigation on the left screen

Figure 1: bottom navigation shifts the options to one screen

Fragment handler

The fragment handler is a helper class to restore fragments that are needed after a screen transition (such as from single-screen to dual-screen).

Surface Duo layout

The Surface Duo layout has been described in a previous blog post, including its design-time support. This is our most powerful layout control and lets you define layouts for single-screen and dual-screen and helps manage them as the app changes state. The screenshots below demonstrate some of the different layout/orientation combinations that are possible, but you can also span a single layout over both screens:

Four Surface Duo emulator images with different dual-screen layouts

Figure 2: single and dual-screen layouts

Frame layout

The frame layout will be helpful for existing apps migrating to dual-screen support asit will move a view to either screen (or allow it to span both). This can be an interim step as you enhance for dual-screen, or a design choice for some modal views in your app. Here’s a screenshot of the frame layout sample where you can interactively shift a view between screens or across the spanned app window:

Surface Duo emulator showing frame layout on right screen

Figure 3: frame layout shifts a view to one side

Tabs

Similar to bottom navigation, tab usage on dual-screens might result in some options being hidden by the hinge. The dual-screen tab layout lets you configure the tabs to group on either screen so that all options are visible:

Surface Duo emulator showing tabs on the right screen

Figure 4: tabs shifts the options to one screen

Resources and feedback 

Visit the docs and sample code to learn more and try these new controls in your apps. You will notice from the gradle configuration that these controls are still in alpha/preview. Please provide us with your feedback on the SDK GitHub repo.

We would also love to hear from you about your overall experience using the SDK, emulator, and what helpers or controls you’d like us to work on next. Please reach out using our feedback forum or message me GitHub

0 comments

Leave a comment