Hello Jetpack Compose developers!
This week, we’d like to announce the release of WindowState, a new utility library that’s part of our Compose SDK. Our goal was to provide easy access to all the window information provided by the Jetpack Window Manager library and to simplify the logic required to enhance your apps for large screens and foldables.
Library overview
The main features of the library are the WindowState data class, which contains three categories of information, and the rememberWindowState()
helper function.
data class WindowState( val hasFold: Boolean = false, val isFoldHorizontal: Boolean = false, val foldBounds: Rect = Rect(), val foldState: FoldState = FoldState.FLAT, val foldSeparates: Boolean = false, val foldOccludes: Boolean = false, val windowWidth: Dp = 0.dp, val windowHeight: Dp = 0.dp, ) @Composable fun Activity.rememberWindowState(): WindowState
Figure 1. Constructor for the WindowState data class and function signature for rememberWindowState().
Fold properties
The WindowState class encapsulates all of the fold data that can be extracted from Jetpack Window Manager’s WindowLayoutInfo and FoldingFeature classes. As shown above, the properties passed into the WindowState constructor are all publicly accessible values, and we also added a few other properties that might be helpful in your app’s logic:
val foldablePaneWidth: Int
The foldablePaneWidth
property returns the width (in pixels) of a single pane of a dual-screen or foldable device when the device is in dual-screen mode. If the device is in single-screen mode, or the device is a regular single-screen device, the return value will be 0. (Note: the return value is based on the assumption that the developer wants two panes of equal width)
val foldSize: Int
The foldSize
property returns the width (in pixels) of the hinge of dual-screen device or the folding line of foldable device when the device is in dual-screen mode. If the device is in single-screen mode, or the device is a regular single-screen device, the return value will be 0.
Window size
The WindowState class also contains properties related to large screens. As you can see in constructor, the class accepts the height and width of the current window, then uses this information to calculate the corresponding WindowSizeClass
for both window dimensions. Our implementation follows the official Android guidance for how to partition windows into the three size classes.
The window dimensions passed into the constructor are public, so these can be accessed at any time. In addition, the calculated size classes for the window can be accessed via the following getters:
fun widthSizeClass(): WindowSizeClass fun heightSizeClass(): WindowSizeClass
Figure 2. Getter methods for window width and height size classes
Window mode
Lastly, WindowState makes it simple to calculate the current window mode, which is helpful when making decisions about your app’s layout. We’ve provided several properties and getters that help you determine which of the four window modes is currently in use:
val windowMode: WindowMode fun isDualScreen(): Boolean fun isDualPortrait(): Boolean fun isDualLandscape(): Boolean fun isSinglePortrait(): Boolean fun isSingleLandscape(): Boolean
Figure 3. Public properties and getter methods for window mode information
To make the library as flexible as possible, we’ve given you the option to access the windowMode
directly, which is useful for choosing between different layouts in a when
block, or to simply ask whether the current window is in a specific mode, which is useful as a state to pass to composables.
Get started
Add to your project
To start using the WindowState library, follow these steps:
-
Add the following dependency to your build.gradle file:
implementation "com.microsoft.device.dualscreen:windowstate:1.0.0-alpha1"
-
Call the
rememberWindowState()
function from your MainActivity and pass the result into your top-level composableclass MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ExampleAppTheme { ExampleApp(rememberWindowState()) } } } }
-
Access the WindowState properties within your composables and use them to make layout decisions
fun ExampleApp(windowState: WindowState) { if (windowState.isDualScreen()) DualScreenAppContent(windowState.foldSize) else SingleScreenAppContent() }
For more detailed instructions and API reference information, please refer to the WindowState README.
Example usage
To see some of examples of how to use the library, you can check out a few different samples.
In the SDK repo, we created a small sample to showcase all of the properties that can be accessed via WindowState.
Figure 4. Screenshots of the library sample in single portrait mode and dual landscape mode on the Surface Duo emulator.
Figure 5. Screenshots of the library sample on other large screen and foldable emulators (clockwise from the top: 6.7 Horizontal Fold-in, 7.6 Fold-in with outer display, Pixel C).
We’ve also updated each of our Compose samples to use WindowState. For an example of how foldable properties can be used, check out the updated TwoPage sample. To see how you can use windowMode
inside a when
block, check out the updated CompanionPane sample. If you would prefer to check whether the window is in a specific mode, you can refer to the ListDetail sample to see how isDualPortrait()
is used.
In our samples, we definitely noticed that using WindowState helped simplify our app logic, and we hope it does the same for you! Since this is the first version of the library, please don’t hesitate to send us feedback on how you think future versions could be improved 😊
Resources and Feedback
Check out the Surface Duo Jetpack Compose developer documentation and past blog posts for links and details on all our samples. You can find our Jetpack Compose samples 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, join us live on Twitch at 11am PST to discuss the WindowState library, Jetpack Window Manager, and any other Surface Duo developer questions you might have.
0 comments