Use JWM WindowSizeClass in WindowState (#51)

* Update JWM version

* Remove custom WindowSizeClass implementation

* Update default width/height value to be greater than 0

* Add new window size class tests

* Update dependencies

* Bump version and update readme
This commit is contained in:
Kristen Halper 2022-11-22 09:33:48 -08:00 коммит произвёл GitHub
Родитель 8c8f972394
Коммит 613ae1ecfe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 69 добавлений и 101 удалений

Просмотреть файл

@ -24,7 +24,7 @@ And the window size classes are measured based on Google's [Window size classes]
2. Add dependencies to the module-level **build.gradle** file (current version may be different from what's shown here). 2. Add dependencies to the module-level **build.gradle** file (current version may be different from what's shown here).
```gradle ```gradle
implementation "com.microsoft.device.dualscreen:windowstate:1.0.0-alpha06" implementation "com.microsoft.device.dualscreen:windowstate:1.0.0-alpha07"
``` ```
3. Also ensure the compileSdkVersion is set to API 33 and the targetSdkVersion is set to API 32 or newer in the module-level build.gradle file. 3. Also ensure the compileSdkVersion is set to API 33 and the targetSdkVersion is set to API 32 or newer in the module-level build.gradle file.
@ -160,14 +160,14 @@ Check if the device window is in the single landscape posture, with which the de
```kotlin ```kotlin
@Composable @Composable
fun widthSizeClass(): WindowSizeClass fun widthSizeClass(): WindowWidthSizeClass
``` ```
Returns the width window size class: **Compact**, **Medium**, **Expanded**, based on the width of the window. Returns the width window size class: **Compact**, **Medium**, **Expanded**, based on the width of the window.
```kotlin ```kotlin
@Composable @Composable
fun heightSizeClass(): WindowSizeClass fun heightSizeClass(): WindowHeightSizeClass
``` ```
Returns the height window size class: **Compact**, **Medium**, **Expanded**, based on the height of the window. Returns the height window size class: **Compact**, **Medium**, **Expanded**, based on the height of the window.
@ -221,13 +221,13 @@ Returns whether a fold occludes content in the window.
Based on the [occlusionType](https://developer.android.com/reference/androidx/window/layout/FoldingFeature#occlusionType()) field in [FoldingFeature](https://developer.android.com/reference/androidx/window/layout/FoldingFeature). Based on the [occlusionType](https://developer.android.com/reference/androidx/window/layout/FoldingFeature#occlusionType()) field in [FoldingFeature](https://developer.android.com/reference/androidx/window/layout/FoldingFeature).
```kotlin ```kotlin
val windowWidthDp: Dp = 0.dp val windowWidthDp: Dp = 1.dp
``` ```
Returns the window width in Dp. Returns the window width in Dp.
```kotlin ```kotlin
val windowHeightDp: Dp = 0.dp val windowHeightDp: Dp = 1.dp
``` ```
Returns the window height in Dp. Returns the window height in Dp.

Просмотреть файл

@ -14,11 +14,11 @@ ext {
// WindowState library version code: // WindowState library version code:
// If you want to publish a new version, bump in one (1) the specific line(s) // If you want to publish a new version, bump in one (1) the specific line(s)
windowStateVersionCode = 6 windowStateVersionCode = 7
// WindowState library version name: // WindowState library version name:
// If you want to publish a new version, bump the specific line // If you want to publish a new version, bump the specific line
windowStateVersionName = '1.0.0-alpha06' windowStateVersionName = '1.0.0-alpha07'
// ---------------------------------- // ----------------------------------
@ -46,15 +46,16 @@ ext {
// AndroidX dependencies // AndroidX dependencies
appCompatVersion = '1.5.1' appCompatVersion = '1.5.1'
ktxCoreVersion = '1.9.0' ktxCoreVersion = '1.9.0'
windowVersion = "1.0.0" windowVersion = "1.1.0-alpha04"
androidxDependencies = [ androidxDependencies = [
appCompat : "androidx.appcompat:appcompat:$appCompatVersion", appCompat : "androidx.appcompat:appcompat:$appCompatVersion",
ktxCore : "androidx.core:core-ktx:$ktxCoreVersion", ktxCore : "androidx.core:core-ktx:$ktxCoreVersion",
window : "androidx.window:window:$windowVersion" window : "androidx.window:window:$windowVersion",
windowCore : "androidx.window:window-core:$windowVersion"
] ]
// Compose dependencies // Compose dependencies
composeVersion = "1.3.0" composeVersion = "1.3.1"
composeCompilerVersion = "1.3.2" composeCompilerVersion = "1.3.2"
activityComposeVersion = '1.6.1' activityComposeVersion = '1.6.1'
navigationComposeVersion = "2.5.3" navigationComposeVersion = "2.5.3"
@ -68,15 +69,16 @@ ext {
] ]
// Test dependencies // Test dependencies
androidxTestVersion = '1.4.0' androidxTestVersion = '1.5.0'
espressoVersion = "3.4.0" androidxTestRunnerVersion = '1.5.1'
espressoVersion = "3.5.0"
junitVersion = '4.13.2' junitVersion = '4.13.2'
mockitoVersion = '4.8.1' mockitoVersion = '4.9.0'
uiAutomatorVersion = "2.2.0" uiAutomatorVersion = "2.2.0"
testDependencies = [ testDependencies = [
androidxTestCore : "androidx.test:core:$androidxTestVersion", androidxTestCore : "androidx.test:core:$androidxTestVersion",
androidxTestRules : "androidx.test:rules:$androidxTestVersion", androidxTestRules : "androidx.test:rules:$androidxTestVersion",
androidxTestRunner : "androidx.test:runner:$androidxTestVersion", androidxTestRunner : "androidx.test:runner:$androidxTestRunnerVersion",
composeUITest : "androidx.compose.ui:ui-test:$composeVersion", composeUITest : "androidx.compose.ui:ui-test:$composeVersion",
composeJunit : "androidx.compose.ui:ui-test-junit4:$composeVersion", composeJunit : "androidx.compose.ui:ui-test-junit4:$composeVersion",
composeUITestManifest : "androidx.compose.ui:ui-test-manifest:$composeVersion", composeUITestManifest : "androidx.compose.ui:ui-test-manifest:$composeVersion",

Просмотреть файл

@ -67,6 +67,7 @@ dependencies {
implementation androidxDependencies.ktxCore implementation androidxDependencies.ktxCore
implementation androidxDependencies.appCompat implementation androidxDependencies.appCompat
implementation androidxDependencies.window implementation androidxDependencies.window
implementation androidxDependencies.windowCore
implementation composeDependencies.composeUI implementation composeDependencies.composeUI
implementation composeDependencies.composeRuntime implementation composeDependencies.composeRuntime

Просмотреть файл

@ -11,6 +11,8 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.height import androidx.compose.ui.unit.height
import androidx.compose.ui.unit.width import androidx.compose.ui.unit.width
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
@ -98,8 +100,8 @@ class WindowStateTest {
assertEquals(FoldState.FLAT, windowState.foldState) assertEquals(FoldState.FLAT, windowState.foldState)
assertEquals(false, windowState.foldIsSeparating) assertEquals(false, windowState.foldIsSeparating)
assertEquals(false, windowState.foldIsOccluding) assertEquals(false, windowState.foldIsOccluding)
assertEquals(0.dp, windowState.windowWidthDp) assertEquals(1.dp, windowState.windowWidthDp)
assertEquals(0.dp, windowState.windowHeightDp) assertEquals(1.dp, windowState.windowHeightDp)
} }
@Test @Test
@ -357,4 +359,37 @@ class WindowStateTest {
windowState.largeScreenPane1Weight = 0.7f windowState.largeScreenPane1Weight = 0.7f
assertEquals(0.7f, windowState.largeScreenPane1Weight) assertEquals(0.7f, windowState.largeScreenPane1Weight)
} }
/**
* windowSizeClass tests
* -------------------------------
*/
@Test
fun compact_window_size_class() {
// Compact width
assertEquals(WindowWidthSizeClass.COMPACT, noFoldCompact.widthSizeClass())
// Compact height
assertEquals(WindowHeightSizeClass.COMPACT, noFoldCompact.heightSizeClass())
assertEquals(WindowHeightSizeClass.COMPACT, noFoldMediumWidthCompactHeight.heightSizeClass())
}
@Test
fun medium_window_size_class() {
// Medium width
assertEquals(WindowWidthSizeClass.MEDIUM, noFoldMediumWidthMediumHeight.widthSizeClass())
// Medium height
assertEquals(WindowHeightSizeClass.MEDIUM, noFoldMediumWidthMediumHeight.heightSizeClass())
assertEquals(WindowHeightSizeClass.MEDIUM, noFoldExpandedWidthMediumHeight.heightSizeClass())
}
@Test
fun expanded_window_size_class() {
// Expanded width
assertEquals(WindowWidthSizeClass.EXPANDED, noFoldExpandedWidthMediumHeight.widthSizeClass())
// Expanded height
assertEquals(WindowHeightSizeClass.EXPANDED, noFoldLargeScreen.heightSizeClass())
}
} }

Просмотреть файл

@ -1,30 +0,0 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
package com.microsoft.device.dualscreen.windowstate
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
enum class WindowSizeClass { COMPACT, MEDIUM, EXPANDED }
/**
* Calculates size class for a given dimension
*
* @param dimenDp: size of dimension in Dp
* @param dimen: which dimension is being measured (width or height)
*/
fun getWindowSizeClass(dimenDp: Dp, dimen: Dimension = Dimension.WIDTH): WindowSizeClass =
when (dimen) {
Dimension.WIDTH -> getSizeClass(dimenDp, 600.dp, 840.dp)
Dimension.HEIGHT -> getSizeClass(dimenDp, 480.dp, 900.dp)
}
private fun getSizeClass(size: Dp, medium: Dp, expanded: Dp): WindowSizeClass = when {
size < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative")
size < medium -> WindowSizeClass.COMPACT
size < expanded -> WindowSizeClass.MEDIUM
else -> WindowSizeClass.EXPANDED
}

Просмотреть файл

@ -17,6 +17,9 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.height import androidx.compose.ui.unit.height
import androidx.compose.ui.unit.width import androidx.compose.ui.unit.width
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
/** /**
* Data class that contains foldable and large screen information extracted from the Jetpack * Data class that contains foldable and large screen information extracted from the Jetpack
@ -38,8 +41,8 @@ data class WindowState(
val foldState: FoldState = FoldState.FLAT, val foldState: FoldState = FoldState.FLAT,
val foldIsSeparating: Boolean = false, val foldIsSeparating: Boolean = false,
val foldIsOccluding: Boolean = false, val foldIsOccluding: Boolean = false,
val windowWidthDp: Dp = 0.dp, val windowWidthDp: Dp = 1.dp,
val windowHeightDp: Dp = 0.dp, val windowHeightDp: Dp = 1.dp,
) { ) {
/** /**
* Dp value of the width of the hinge or the folding line if it is separating, otherwise 0 * Dp value of the width of the hinge or the folding line if it is separating, otherwise 0
@ -143,13 +146,16 @@ data class WindowState(
return windowMode == WindowMode.SINGLE_LANDSCAPE return windowMode == WindowMode.SINGLE_LANDSCAPE
} }
private val windowSizeClass
get() = WindowSizeClass.compute(dpWidth = windowWidthDp.value, dpHeight = windowHeightDp.value)
/** /**
* Returns the size class (compact, medium, or expanded) for the window width * Returns the size class (compact, medium, or expanded) for the window width
* *
* @return width size class * @return width size class
*/ */
fun widthSizeClass(): WindowSizeClass { fun widthSizeClass(): WindowWidthSizeClass {
return getWindowSizeClass(windowWidthDp) return windowSizeClass.windowWidthSizeClass
} }
/** /**
@ -157,8 +163,8 @@ data class WindowState(
* *
* @return height size class * @return height size class
*/ */
fun heightSizeClass(): WindowSizeClass { fun heightSizeClass(): WindowHeightSizeClass {
return getWindowSizeClass(windowHeightDp, Dimension.HEIGHT) return windowSizeClass.windowHeightSizeClass
} }
/** /**
@ -234,7 +240,8 @@ data class WindowState(
*/ */
private fun windowIsLarge(): Boolean { private fun windowIsLarge(): Boolean {
// Window is large if width size class is expanded and height size class is at least medium // Window is large if width size class is expanded and height size class is at least medium
val isLarge = widthSizeClass() == WindowSizeClass.EXPANDED && heightSizeClass() != WindowSizeClass.COMPACT val isLarge = widthSizeClass() == WindowWidthSizeClass.EXPANDED &&
heightSizeClass() != WindowHeightSizeClass.COMPACT
// Right now we are considering large screens + foldables mutually exclusive // Right now we are considering large screens + foldables mutually exclusive
// (which seems necessary for dualscreen apps), but we may want to think about this // (which seems necessary for dualscreen apps), but we may want to think about this

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
package com.microsoft.device.dualscreen.windowstate
import androidx.compose.ui.unit.dp
import org.junit.Assert.assertEquals
import org.junit.Test
class WindowSizeClassTest {
@Test
fun width_returns_compact() {
assertEquals(WindowSizeClass.COMPACT, getWindowSizeClass(500.dp, Dimension.WIDTH))
assertEquals(WindowSizeClass.COMPACT, WindowState(windowWidthDp = 500.dp).widthSizeClass())
}
@Test
fun width_returns_medium() {
assertEquals(WindowSizeClass.MEDIUM, getWindowSizeClass(700.dp, Dimension.WIDTH))
assertEquals(WindowSizeClass.MEDIUM, WindowState(windowWidthDp = 700.dp).widthSizeClass())
}
@Test
fun width_returns_expanded() {
assertEquals(WindowSizeClass.EXPANDED, getWindowSizeClass(900.dp, Dimension.WIDTH))
assertEquals(WindowSizeClass.EXPANDED, WindowState(windowWidthDp = 900.dp).widthSizeClass())
}
@Test
fun height_returns_compact() {
assertEquals(WindowSizeClass.COMPACT, getWindowSizeClass(300.dp, Dimension.HEIGHT))
assertEquals(WindowSizeClass.COMPACT, WindowState(windowHeightDp = 300.dp).heightSizeClass())
}
@Test
fun height_returns_medium() {
assertEquals(WindowSizeClass.MEDIUM, getWindowSizeClass(700.dp, Dimension.HEIGHT))
assertEquals(WindowSizeClass.MEDIUM, WindowState(windowHeightDp = 700.dp).heightSizeClass())
}
@Test
fun height_returns_expanded() {
assertEquals(WindowSizeClass.EXPANDED, getWindowSizeClass(1000.dp, Dimension.HEIGHT))
assertEquals(WindowSizeClass.EXPANDED, WindowState(windowHeightDp = 1000.dp).heightSizeClass())
}
}

Просмотреть файл

@ -56,6 +56,7 @@ dependencies {
implementation androidxDependencies.ktxCore implementation androidxDependencies.ktxCore
implementation androidxDependencies.appCompat implementation androidxDependencies.appCompat
implementation androidxDependencies.window implementation androidxDependencies.window
implementation androidxDependencies.windowCore
implementation composeDependencies.composeUI implementation composeDependencies.composeUI
implementation composeDependencies.composeMaterial implementation composeDependencies.composeMaterial
implementation composeDependencies.composeUITooling implementation composeDependencies.composeUITooling