Stretching the UX of Android Apps for Foldable Phones

Javier Marsicano
ProAndroidDev
Published in
5 min readNov 15, 2021

--

Photo by Mika Baumeister on Unsplash

Mobile device concept is one step ahead of the trend in technology, bringing an enhanced visual experience to the palm of our hands with Foldable phones. This new form factor allows users to “stretch” the screen to a double size of a standard phone for better visualization, and also “reduce” the screen size to fit into your pocket as well.

Most of the well-known manufacturers have released several foldable device models tailored to different preferences. Hence, mobile apps would offer a user experience that might fit more than one fixed size of screen for a single device. Furthermore, they could take advantage of this to offer an immersive multimedia experience.

Consequently, apps must avoid wasting screen size with empty space that could be occupied by an informational or interactive element, namely button, text, panel, menu, etc.

Programming tools

To make apps foldable-aware, Google has provided some tools with Android Jetpack within a new WindowManager API that enables apps to benefit from screen size change. The official documentation is good enough to introduce the concepts, however, it isn’t enough for a hands-on adoption.

Though there are some thorough articles and sample projects, they are too complex to understand the basics of the API and its mechanisms. Like all hardware and sensor events, we can use several techniques to detect screen changes asynchronously; so Android Jetpack provides a high level API to hook with user events through three different asynchronous programming approaches: Callbacks, Kotlin Flow and RxJava. Most of the sample code we can find on the web uses either the old school callbacks, or Flow — which is not considered an API ready for production — and also, there are many Android apps that haven’t implemented Kotlin-first philosophy. Thus, this article aims to give a concrete, yet simple guide to implement foldable-aware features using RxJava.

Show me the code

Indeed, a foldable phone screen might have two states, open (flat) and closed (folded). But most foldable devices bring the capability of another quite useful intermediate state when the device is partially folded: Half-opened, also called Flex mode. This state is of a special interest because it allows users to have two logical screens with a single big screen, so that some UI elements such as controls or menu can be placed on one of them and the content itself is shown on the other one for instance. Therefore our apps should listen for these events and make changes on the UI to adapt or optimize the interaction.

Screen states for a foldable device

First of all we should add the dependency in app module build.gradle file

androidx.window:window-rxjava2:$windowVersion

Then it is recommended to make activities resizeable by declaring the setting in manifest:

android:resizeableActivity

Now we are able to use the API to listen for fold states. We need an instance of WindowRepository that can be obtained from context

context.windowInfoRepository()

Finally we can use that instance to observe the stream of state changes

disposable = windowInfoRepository
.windowLayoutInfoObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(callback)

As we can see, we should make sure we can dispose the stream as soon as it is necessary by calling disposable.dispose() as a good practice when working with RxJava. Likewise, since the observer will be called by a background thread and we need to update the UI it is necessary to switch to the main thread. The callback receives as a parameter an instance of WindowLayoutInfo which contains all the information needed inside the displayFeatures field, though its elements should be casted to FoldingFeature. The state field can be FoldingFeature.State.HALF_OPENED or FoldingFeature.State.FLAT. When displayFeatures is empty the screen is folded (closed); we should consider that state as a standard device screen.

So let’s say your app has a RecyclerView with large items that have been listed as a LinearLayout. But now when the user unfolds the device you can have a grid of elements. We could change its layout manager according to the state changes.

So the full code that implements this logic is the following:

This way we get a simple and basic foldable app that helps to understand and implement the functionality with an easy approach. But for sure, there should be some more logic around it considering hinge, device orientation while the screen is fully open, in vertical (Book mode) and landscape (TableTop mode). Also, we can optimize more precisely by calculating WindowMetrics as well as changing constraint layout settings or by using the ReactiveGuide component with animated transitions.

All of these depend on the user experience your app should offer and the content it is meant to show, whether video, text or controls. There are several UX design guidelines for foldables you should consider for your app.

One final note is that I’d recommend using feature toggles and A/B testing when developing first foldable-aware features. In Particular, the app should send the device model to the backend that it is consuming services from, so that it can deliver exclusive content for foldable devices, for example videos with higher resolution.

Testing

It could be a pain to buy a foldable phone just for debugging and testing purposes, but the good news is that there are some useful emulators that can be used to run our new foldable aware app.
You may test foldable devices with Android Emulator version 30.1.1 or newer which can be installed with Android Studio 4.2 and above.

When creating a new virtual device with AVD Manager you can choose 7.6” Fold-in with outer display — which is quite similar to Galaxy Z , 8” Fold-out or 6.7” Horizontal Fold-in; even the Surface Duo emulator works well.

Monitoring

As mentioned above I recommend using feature toggles or flags when publishing an app to the Play Store . This way you’ll know exactly what to turn off in case of a terrible release. We’ll be publishing our app to Google Play Store shortly and to prepare for onboarding new users, we’regoing to be monitoring the app in production. With Sentry.io my team will get notified in real time of any production errors or performance issues and relay how a release is trending. If a release is seeing a lot of new errors or crashed sessions, I can quickly flip my feature toggle and then bounce back to Sentry to see if that resolved the issue or publish a new package. Additionally, we can filter issues by device, so if we need to search for foldable device ones we could search device:SM-F926U which is one of the device model id of Galaxy Z Fold 2. This way we can identify performance issues by measuring UI rendering on a larger screen for instance. Integrating Sentry is quick and straightforward, just declare the dependency io.sentry:sentry-android:<version number> and add to the manifest the key provided when creating an account:

<application>
<meta-data android:name="io.sentry.dsn" android:value="https://<key>@sentry.io/<project>" />
</application>

There are already many apps that have been leveraging foldable features, so we should keep an eye on them as a reference.

I hope you found this article helpful, please share your thoughts and feedback about the experience with foldable devices.

--

--