isSeparating: the field that unites all foldables

Cesar Valiente

Hello Android developers,

Today we are going to talk about a very useful field that is part of Jetpack Window Manager library. This field is called isSeparating, and will help you to understand when there is content separated by a FoldingFeature on a foldable device.

The value of isSeparating will be false if there is no content that is separated by a hinge or a fold.

The value of isSeparating will be true if there is content that is separated by a hinge or a fold.

Is this field and the value it holds valid for all kinds of foldable devices, no matter how many physical displays or types of hinges they have? Yes, this field has you covered no matter what the foldable device is. One field to rule them all! 😊

Wait, wait! too fast Cesar! Ok, ok, let’s take a step back.

Understanding the different foldable scenarios that we have

Until very recently, we had just one kind of device: single-screen. A single-screen device could be a phone with a small display, a tablet with a large one, or a TV with an even larger one. No matter the size, it was a continuous display without anything that could occlude its content and without the possibility to change its posture; it was just flat.

Now, foldable devices have entered the game. Foldable devices, as you may know, currently have one display that can be folded or two independent displays that can be folded through a physical hinge. Foldable devices can also have different postures – not just different orientations (portrait and landscape), but different postures – such as mirroring a tabletop, a book, a tent, etc. A foldable device can take these different postures because of its FoldingFeature, which is where the device folds. As briefly mentioned above, we currently have two kinds of FoldingFeatures:

  • Hinge – joins two physical and independent displays. Surface Duo is a device that has a hinge.
  • Fold – the area where a foldable device with just one physical display can be folded.

In this new scenario, where devices can have multiple displays and/or displays that can be folded, we should provide UIs that handle these new scenarios and configurations, especially those that take advantage of the more available display area to provide a fantastic user experience.

Three different examples of device posture - book-like, laptop-like, and tented which is folded over 240 degrees

Figure 1. Some of the postures that a foldable device can take.

Let’s think about a foldable that is folded 90 degrees and that takes a tabletop posture. In this posture, content that is located in the folded area is pretty much unusable, and users won’t be able to see the content there correctly nor able to interact with its UI. The same happens when the foldable device takes a different posture, such as book, where now the FoldingFeature is vertical, and the content located there is not accessible nor visible correctly.

And what about Surface Duo that has two physical displays separated by a physical hinge? In the case of this device, the FoldingFeature is always separating the content when the app is spanned across displays and uses the whole display area. The device can also take the same postures that we have mentioned above, such as tabletop and book (and even more!), and in these postures there is also content that is not accessible nor visible.

Here is where isSeparating from Jetpack Window Manager will help you!

isSeparating

As we have mentioned briefly in the introduction, isSeparating is part of Jetpack Window Manager. This field will help us to understand when a FoldingFeature is separating the content.

When is the content separated in a foldable device?

  • In a foldable device with a continuous display with a fold area: when the device is in a posture where the content is difficult to access or to visualize, postures like tabletop and book, where the device is in a half-opened posture.
  • In a foldable device with two independent displays separated by a hinge: the content, when the app is using the whole display area (both displays) will be always separated by the hinge, no matter the posture that takes.

The value of isSeparating will be true or false depending on whether the content is separated or not.

Do you want to see the internals of that field? Let’s see:

override val isSeparating: Boolean
   get() = when {
       type == Type.HINGE -> true
       type == Type.FOLD && state == FoldingFeature.State.HALF_OPENED -> true
       else -> false
   }

Figure 2. isSeparating field (find the source code in the AndroidX repository)

As you can see the code is simple but very powerful!

How can we use isSeparating in our apps?

If you have been following us, you may know how Jetpack Window Manager works and how to get its WindowLayoutInfo, but once again, first thing we have to do is to register for changes:

lifecycleScope.launch(Dispatchers.Main) {
   lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED {
      WindowInfoTracker.getOrCreate(this@MainActivity)
         .windowLayoutInfo(this@MainActivity)
         .collect {newLayoutInfo ->
            updateCurrentLayout(newLayoutInfo)
         }
   }
}

Figure 3. Initializing Window Manager

As you can see, once we get new WindowLayoutInfo (inside collect), we will handle the UI and apply the changes we want depending on if the content is separated by the FoldingFeature or not.

In the function updateCurrentLayout:

private fun updateCurrentLayout(newLayoutInfo: WindowLayoutInfo) {
   for (displayFeature in newLayoutInfo.displayFeatures) {
      val foldFeature = displayFeature as? FoldingFeature
      foldFeature?.let {
         if (it.isSeparating) {
  		//The content is separated by the FoldingFeature.
  		//Here is where you should adapt your UI.
         }  
         else {
  		//The content is not separated.
  		//Users can see and interact with your UI properly.
         }
      }
   }
}

Figure 4. Using isSeparating to know whether the content is separated or not

Easy, right? As you can see, we just get the foldFeature value and see the value isSeparating has, and with that we then know whether the content is being separated or not so we can decide whether or not to make changes in our UI.

Remember that isSeparating works for all foldable devices! No matter the hinge, the display, the posture the device has, etc. isSeparating will tell you whether the content is being separated or not.

isSeparating-sample app

Do you want to see in action how isSeparating works, and how we can enhance the UI to provide a better user experience in all scenarios?

We have created a very simple application where we change the UI depending on whether the content is being separated or not. To make the app we have relied heavily on a couple of components: MotionLayout and ReactiveGuide. These components will help us to build a dynamic UI that can be adapted whenever there is a FoldingFeature that separates the content and adds a bit of motion, making it easier to see the applied changes.

The app basically shows text when its content is not separated, and when it is, the UI is adapted to show new text on the other side of the FoldingFeature that indicates if the FoldingFeature is in a horizontal or vertical orientation.

Let’s see the app in action in a couple of animations:

Figure 5. Sample app running in a foldable device

As you see above, when we run the app in a foldable device, when the FoldingFeature is not separating the content (the device is in a flat posture), we see just one text (“isSeparating?”).

But when we change its posture to half-open, so the device is folded 90 degrees adopting a tabletop posture, isSeparating value will be true and we will adjust the UI accordingly showing a different one.

Let’s see now the same app running on Surface Duo, a dual-screen device:

Animation of a foldable device showing when isSeparating becomes true or false based on the fold angle

Figure 6. Sample app running in a dual-screen device.

In dual-screen devices, when the app runs in single-screen mode, there is no interaction with the FoldingFeature, hence the content is not separated, so we show just the initial text; but when the app is spanned across displays, as we have mentioned before, since the device has two physical displays separated by a physical hinge, its content is always separated, and we show the different UI.

More samples and docs?

Google has started to use isSeparating as well in the apps that are getting enhanced with foldable support. Jetcaster is a sample podcast app built with Jetpack Compose that uses Jetpack Window Manager to make its UI foldable aware. They recently updated the app to use isSeparating to create a UI that is enhanced whenever the FoldingFeature separates the content, so now Jetcaster works well on all kinds of foldable devices.

Google has also very recently updated their fantastic foldable docs covering also isSeparating functionality and the values that can get depending on the different scenarios (that we also have seen in this blog post).

We also provide a lot of other different samples where we use Jetpack Window Manager and isSeparating to enhance dynamically the apps’ UI, and in fact, most of them are more complex and more-real scenarios than the basic sample we have seen here. Many of them are in our WindowManager samples repo, and also our Jetpack Compose libraries repo make use of the field.

We also have you covered in terms of docs. We have a complete section where we cover Jetpack Window Manager (including isSeparating) and libraries around it such as SlidingPaneLayout.

Resources and feedback

The code for the isSeparating-sample is available on GitHub.

If you have any questions, or would like to tell us about your apps, use the feedback forum or message us on Twitter @surfaceduodev.

Finally, please join us for our dual-screen developer livestream at 11am (Pacific time) each Friday – mark it in your calendar and check out the archives on YouTube.