1. Introduction

Yes, there’s a new addition to Jetpack, WindowManager. What does it do? This article will take you to understand.

WindowManager is the latest feature in Android Jetpack and is designed to help APP developers support new device sizes and provide common API interactions for various WindowManager features on both old and new platform versions. For now, the initial version is for foldable devices, and future versions will be expanded to support more display types and windowing capabilities.

2. Why do we need it?

Now there are some new devices on the market that offer a unique set of hardware features. Optimizing your APP for these new devices and shapes can create a unique experience for users and allow them to make the most of their devices.

The Samsung Galaxy Z Flip, for example, is a clamshell device that supports fold and partially fold states (what Samsung calls Flex mode). When the device is partially collapsed, the application can optimize its layout and separate the controls at the bottom from the rest of the content at the top. For example, the camera or gallery may be adapted as follows:

Users can place the phone in a flat place (on a desk, for example) and then use the bottom half of the screen to navigate and interact with apps.


The goal of the Jetpack WindowManager library is to provide a single upper-layer API for all types of foldable devices on the market so that developers can adapt to different types of devices, rather than individually to each device model.

In version 1.0.0, the library provides information about two physical properties of a collapsible device – display characteristics and device state.

  • DisplayFeature: This API recognizes whether the screen surface is continuous, such as hinged or folded.
  • DeviceState: This API uses a defined list of states (e.gCLOSED.OPENED.HALF_OPENEDEtc.) to provide the current status of the phone.

3. Display features

A single display panel or multiple display configurations may have different features that create interference on continuous screen surfaces, such as folds, hinges, curved areas or bangs. If there are such interrupts in an application window, you can adjust the layout and placement of content in the window to avoid such areas showing exceptions, or to use them as natural separators. This also shows the advantages of such devices.

Each display feature region can be represented by its boundary rectangle and its type in the window coordinate space. The rectangle indicates the physical range of the feature. The type of feature will help define how to treat it. For example, some features can create physical separators and/or non-interactive areas (e.g., hinge between two display panels to show cuts), while others can be used as logical separators (e.g., folds).

public class DisplayFeature {
    private Rect mRect;
    private @Type int mType;
.}
Copy the code

The first version of Jetpack WindowManager contained only two types of functionality: TYPE_FOLD and TYPE_HINGE.

Specifically for TYPE_FOLD, the bounding rectangle should be either zero-high (0, y, width, y) or zero-wide (x, 0, x, height), which indicates that there are no inaccessible regions, but it still reports the location on the screen.

4. Device status

Depending on the hinge hardware design, different foldable devices can have several intermediate states: closed, partially open, fully open (flat surface) or flipped.

When using Jetpack WindowManager, the APP can provide different functions based on these device states. These states are defined as different postures:

@IntDef({
    POSTURE_UNKNOWN,
    POSTURE_CLOSED,
    POSTURE_HALF_OPENED,
    POSTURE_OPENED,
 POSTURE_FLIPPED }) public @interface Posture{} Copy the code

Each device can capture any subset of these postures defined above, depending on their hardware and the desired user experience.

4. How to use it?

Having said that, how do you use it?

Take your time…

First, you need to add the Window Manager maven repository address to your project by adding the dependency to build.gradle below your app:

Dependencies {implementation "androidx window: window: 1.0.0 - alpha01"}Copy the code

As shown above, let’s say you want to split the user interface of an app like Google Duo on a foldable device. This usually makes sense in cases where the physical configuration and state of the device creates logical isolation for the user.

For example, the Galaxy Z Flip in “Flex” or “fold in half” mode produces this logical separation. Therefore, you need to know where the folds are in the application window and the state of the device.

First of all, from the Activity androidx. Window. WindowManager instance.

var windowManager = WindowManager(this /* context */.null /* windowBackend */)
Copy the code

Pay attention to the parameters here

  • The first argument, Context, is used to initialize a WindowManager instance and connect it to a visual entity on the screen. Therefore, it must be a visual Context, which means it can only be an Activity or a ContextWrapper.

  • WindowBackend is the provider of the library information, where null is passed to indicate that the default device information will be used, and when the application runs on a regular phone, the library reports no display characteristics and unknown device status. However, you can also pass androidx. Window. WindowBackend custom implementation, to simulate any type of folding equipment, without access to physical hardware. We have an example of this in the sample APP :github.com/android/use…

Because UI is only separated if there is logical hardware separation, there are two cases:

1. The display feature is of type TYPE_HINGE, and there is always a physical partition within the active window.

2. Or the display feature is of Type_Fold type and the screen state is not flat (for example, not POSTURE_OPENED). For the Galaxy Z Flip in particular, we would be interested in POSTURE_HALF_OPENED.

In the case of folding, we need to know about DeviceState changes, so we need to register the DeviceState change listener:

windowManager.registerDeviceStateChangeCallback(
    mainThreadExecutor /* Executor */.    callback /* Consumer<DeviceState> */)
Copy the code

In the callback, you can change the device state and update the UI as needed. Finally, we need to capture the actual display characteristics in the active window.

val displayFeatures = windowManager.windowLayoutInfo.displayFeatures
Copy the code

Depending on how your Activity handles (or does not handle) configuration changes, you may need to ask it at different points in the Activity’s life cycle. Then apply it to the Window Decor View layout to make sure it’s always up to date after the Activity status changes. The code is as follows:

window.decorView.doOnLayout {
    val displayFeatures =
        windowManager.windowLayoutInfo.displayFeatures
.}
Copy the code

Note that the position of the display feature is computed relative to the active window coordinate space, so it can only be provided after the Activity is attached to the window. Requesting information before then will throw an exception.

5. The last

It is highly recommended to run the View official Demo to explore Jetpack WindowManager, which also includes examples of how to calculate the position of display features in the View organization, as well as examples such as auto split layout when a split display feature is found, and so on. Demo address: github.com/android/use…

Author Kenneth Ford | | translator is still fant thin west edit | fant thin west address | medium.com/androiddeve…

The article was first published on the public account: “Technology TOP”, there are dry articles updated every day, you can search wechat “technology TOP” first time to read, reply [mind map] [interview] [resume] yes, I prepare some Android advanced route, interview guidance and resume template for you