diff --git a/README.md b/README.md index cbf74869b..a0b46dfde 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ See our [Migration Guide](https://google.github.io/accompanist/navigation-animat ### 🧭🎨️ [Navigation-Material](./navigation-material/) (Deprecated & Removed) See our [Migration Guide](https://google.github.io/accompanist/navigation-material/) for migrating to using built in material-navigation support. -### 🍫 [System UI Controller](./systemuicontroller/) (Deprecated) +### 🍫 [System UI Controller](./systemuicontroller/) (Deprecated & Removed) We recommend migrating to edge to edge. See our [Migration Guide](https://google.github.io/accompanist/systemuicontroller/) for more details. --- diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index fcd2bcb87..7811e0ed8 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -68,7 +68,6 @@ dependencies { implementation(project(":adaptive")) implementation(project(":drawablepainter")) implementation(project(":permissions")) - implementation(project(":systemuicontroller")) implementation(libs.androidx.appcompat) implementation(libs.mdc) diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index dd3312663..c775f431b 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -80,39 +80,6 @@ - - - - - - - - - - - - - - - - - - - - - - 0.5f - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change status bar color") - } - Button( - onClick = { - systemUiController.setNavigationBarColor(clickedColor) - navigationBarDarkIcons = clickedColor.luminance() > 0.5f - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change navigation bar color") - } - Button( - onClick = { - systemUiController.setSystemBarsColor(clickedColor) - statusBarDarkIcons = clickedColor.luminance() > 0.5f - navigationBarDarkIcons = statusBarDarkIcons - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change system bars color") - } - - Row( - modifier = Modifier - .clickable { - statusBarDarkIcons = !statusBarDarkIcons - } - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = "Set status bar dark icons ") - Checkbox( - checked = statusBarDarkIcons, - onCheckedChange = { - statusBarDarkIcons = it - } - ) - } - Row( - modifier = Modifier - .clickable { - navigationBarDarkIcons = !navigationBarDarkIcons - } - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = "Set navigation bar dark icons ") - Checkbox( - checked = navigationBarDarkIcons, - onCheckedChange = { - navigationBarDarkIcons = it - } - ) - } - } - } - } -} diff --git a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/DocsSamples.kt b/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/DocsSamples.kt deleted file mode 100644 index 3ffb7df9b..000000000 --- a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/DocsSamples.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.sample.systemuicontroller - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.ui.graphics.Color -import com.google.accompanist.systemuicontroller.rememberSystemUiController - -@Composable -fun SystemUiControllerSample() { - // Remember a SystemUiController - val systemUiController = rememberSystemUiController() - val useDarkIcons = !isSystemInDarkTheme() - - DisposableEffect(systemUiController, useDarkIcons) { - // Update all of the system bar colors to be transparent, and use - // dark icons if we're in light theme - systemUiController.setSystemBarsColor( - color = Color.Transparent, - darkIcons = useDarkIcons - ) - - // setStatusBarColor() and setNavigationBarColor() also exist - onDispose {} - } -} diff --git a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsColorSample.kt b/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsColorSample.kt deleted file mode 100644 index cec918c54..000000000 --- a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsColorSample.kt +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.sample.systemuicontroller - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.material.Button -import androidx.compose.material.Checkbox -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.core.view.WindowCompat -import coil.annotation.ExperimentalCoilApi -import coil.compose.rememberImagePainter -import com.google.accompanist.sample.AccompanistSampleTheme -import com.google.accompanist.sample.R -import com.google.accompanist.sample.rememberRandomSampleImageUrl -import com.google.accompanist.systemuicontroller.rememberSystemUiController - -class SystemBarsColorSample : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // Turn off the decor fitting system windows, which means we need to through handling - // insets - WindowCompat.setDecorFitsSystemWindows(window, false) - - setContent { - AccompanistSampleTheme { - Sample() - } - } - } -} - -@OptIn(ExperimentalCoilApi::class) -@Composable -private fun Sample() { - // Get the current SystemUiController - val systemUiController = rememberSystemUiController() - var clickedColor by remember { mutableStateOf(Color.Unspecified) } - var statusBarDarkIcons by remember { mutableStateOf(false) } - var navigationBarDarkIcons by remember { mutableStateOf(false) } - - LaunchedEffect(systemUiController, statusBarDarkIcons, navigationBarDarkIcons) { - systemUiController.statusBarDarkContentEnabled = statusBarDarkIcons - systemUiController.navigationBarDarkContentEnabled = navigationBarDarkIcons - } - - @Composable - fun Color(color: Color) { - Box( - modifier = Modifier - .size(54.dp) - .clickable { clickedColor = color }, - contentAlignment = Alignment.Center - ) { - if (clickedColor == color) { - Box( - Modifier - .size(48.dp) - .background(Color.Black.copy(alpha = 0.6f)) - ) - } - Box(modifier = Modifier.size(44.dp)) { - Image( - painter = painterResource(R.drawable.alpha), - contentDescription = null, - contentScale = ContentScale.FillBounds, - modifier = Modifier.fillMaxSize() - ) - Box( - Modifier - .fillMaxSize() - .background(color) - ) - } - } - } - - BoxWithConstraints(Modifier.fillMaxSize()) { - // Displaying a random image - Image( - painter = rememberImagePainter( - data = with(LocalDensity.current) { - rememberRandomSampleImageUrl( - seed = 16, - width = maxWidth.roundToPx(), - height = maxHeight.roundToPx() - ) - } - ), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) - Column(Modifier.fillMaxSize().systemBarsPadding()) { - TopAppBar( - title = { Text(stringResource(R.string.system_ui_controller_title_color)) }, - backgroundColor = MaterialTheme.colors.surface.copy(alpha = 0.5f), - elevation = 0.dp, - ) - Spacer(modifier = Modifier.weight(1f)) - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colors.surface.copy(alpha = 0.5f)) - .padding(vertical = 16.dp), - ) { - Row { - Color(Color.Black) - Color(Color.DarkGray) - Color(Color.Gray) - Color(Color.LightGray) - } - Row { - Color(Color.White) - Color(Color.Red) - Color(Color.Green) - Color(Color.Blue) - } - Row { - Color(Color.Yellow) - Color(Color.Cyan) - Color(Color.Magenta) - Color(Color(0xFF673AB7)) - } - Row { - Color(Color.Black.copy(alpha = 0.5f)) - Color(Color.Blue.copy(alpha = 0.5f)) - Color(Color.White.copy(alpha = 0.5f)) - Color(Color.Transparent) - } - Spacer(modifier = Modifier.height(16.dp)) - Button( - onClick = { - systemUiController.setStatusBarColor(clickedColor) - statusBarDarkIcons = clickedColor.luminance() > 0.5f - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change status bar color") - } - Button( - onClick = { - systemUiController.setNavigationBarColor(clickedColor) - navigationBarDarkIcons = clickedColor.luminance() > 0.5f - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change navigation bar color") - } - Button( - onClick = { - systemUiController.setSystemBarsColor(clickedColor) - statusBarDarkIcons = clickedColor.luminance() > 0.5f - navigationBarDarkIcons = statusBarDarkIcons - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change system bars color") - } - - Row( - modifier = Modifier - .clickable { - statusBarDarkIcons = !statusBarDarkIcons - } - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = "Set status bar dark icons ") - Checkbox( - checked = statusBarDarkIcons, - onCheckedChange = { - statusBarDarkIcons = it - } - ) - } - Row( - modifier = Modifier - .clickable { - navigationBarDarkIcons = !navigationBarDarkIcons - } - .padding(8.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = "Set navigation bar dark icons ") - Checkbox( - checked = navigationBarDarkIcons, - onCheckedChange = { - navigationBarDarkIcons = it - } - ) - } - } - } - } -} diff --git a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsVisibilitySample.kt b/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsVisibilitySample.kt deleted file mode 100644 index 287b93090..000000000 --- a/sample/src/main/java/com/google/accompanist/sample/systemuicontroller/SystemBarsVisibilitySample.kt +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.sample.systemuicontroller - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Button -import androidx.compose.material.DropdownMenu -import androidx.compose.material.DropdownMenuItem -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Scaffold -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.core.view.WindowInsetsControllerCompat -import com.google.accompanist.sample.AccompanistSampleTheme -import com.google.accompanist.sample.R -import com.google.accompanist.systemuicontroller.rememberSystemUiController - -class SystemBarsVisibilitySample : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - AccompanistSampleTheme { - Surface { - Sample() - } - } - } - } -} - -@Composable -private fun Sample() { - // Get the current SystemUiController - val systemUiController = rememberSystemUiController() - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.system_ui_controller_title_visibility)) }, - backgroundColor = MaterialTheme.colors.surface, - ) - }, - modifier = Modifier.fillMaxSize() - ) { padding -> - Column( - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()) - .padding(padding), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Box { - var isShowingDropdownMenu by remember { mutableStateOf(false) } - - Button( - onClick = { - isShowingDropdownMenu = true - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Change System Bars Behavior") - } - - DropdownMenu( - expanded = isShowingDropdownMenu, - onDismissRequest = { isShowingDropdownMenu = false } - ) { - DropdownMenuItem( - onClick = { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_DEFAULT - isShowingDropdownMenu = false - } - ) { - Text("BEHAVIOR_DEFAULT") - } - DropdownMenuItem( - onClick = { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - isShowingDropdownMenu = false - } - ) { - Text("BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE") - } - } - } - - /** Status bar */ - - Button( - onClick = { - systemUiController.isStatusBarVisible = true - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Show the status bar") - } - Button( - onClick = { - systemUiController.isStatusBarVisible = false - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Hide the status bar") - } - - /** Navigation bar */ - - Button( - onClick = { systemUiController.isNavigationBarVisible = true }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Show the navigation bar") - } - Button( - onClick = { - systemUiController.isNavigationBarVisible = false - }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Hide the navigation bar") - } - - /** System bars */ - - Button( - onClick = { systemUiController.isSystemBarsVisible = true }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Show the system bars") - } - Button( - onClick = { systemUiController.isSystemBarsVisible = false }, - modifier = Modifier - .fillMaxWidth(0.7f) - .padding(vertical = 8.dp) - ) { - Text(text = "Hide the system bars") - } - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index b8e09a49b..79d172aa1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -32,11 +32,9 @@ dependencyResolutionManagement { include(":adaptive") include(":internal-testutils") -include(":appcompat-theme") include(":drawablepainter") include(":permissions") include(":permissions-lint") -include(":systemuicontroller") include(":sample") rootProject.name = "accompanist" diff --git a/systemuicontroller/README.md b/systemuicontroller/README.md deleted file mode 100644 index ff340a965..000000000 --- a/systemuicontroller/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# System UI Controller for Jetpack Compose - -[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-systemuicontroller)](https://search.maven.org/search?q=g:com.google.accompanist) - -System UI Controller provides easy-to-use utilities for updating the System UI bar colors within Jetpack Compose. - -For more information, visit the documentation: https://google.github.io/accompanist/systemuicontroller - -## Download - -```groovy -repositories { - mavenCentral() -} - -dependencies { - implementation "com.google.accompanist:accompanist-systemuicontroller:" -} -``` - -Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit. - - - [snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-systemuicontroller/ \ No newline at end of file diff --git a/systemuicontroller/api/current.api b/systemuicontroller/api/current.api deleted file mode 100644 index 56a381804..000000000 --- a/systemuicontroller/api/current.api +++ /dev/null @@ -1,39 +0,0 @@ -// Signature format: 4.0 -package com.google.accompanist.systemuicontroller { - - @Deprecated @androidx.compose.runtime.Stable public interface SystemUiController { - method @Deprecated public boolean getNavigationBarDarkContentEnabled(); - method @Deprecated public boolean getStatusBarDarkContentEnabled(); - method @Deprecated public int getSystemBarsBehavior(); - method @Deprecated public default boolean getSystemBarsDarkContentEnabled(); - method @Deprecated public boolean isNavigationBarContrastEnforced(); - method @Deprecated public boolean isNavigationBarVisible(); - method @Deprecated public boolean isStatusBarVisible(); - method @Deprecated public default boolean isSystemBarsVisible(); - method @Deprecated public void setNavigationBarColor(long color, optional boolean darkIcons, optional boolean navigationBarContrastEnforced, optional kotlin.jvm.functions.Function1 transformColorForLightContent); - method @Deprecated public void setNavigationBarContrastEnforced(boolean); - method @Deprecated public void setNavigationBarDarkContentEnabled(boolean); - method @Deprecated public void setNavigationBarVisible(boolean); - method @Deprecated public void setStatusBarColor(long color, optional boolean darkIcons, optional kotlin.jvm.functions.Function1 transformColorForLightContent); - method @Deprecated public void setStatusBarDarkContentEnabled(boolean); - method @Deprecated public void setStatusBarVisible(boolean); - method @Deprecated public void setSystemBarsBehavior(int); - method @Deprecated public default void setSystemBarsColor(long color, optional boolean darkIcons, optional boolean isNavigationBarContrastEnforced, optional kotlin.jvm.functions.Function1 transformColorForLightContent); - method @Deprecated public default void setSystemBarsDarkContentEnabled(boolean); - method @Deprecated public default void setSystemBarsVisible(boolean); - property @Deprecated public abstract boolean isNavigationBarContrastEnforced; - property @Deprecated public abstract boolean isNavigationBarVisible; - property @Deprecated public abstract boolean isStatusBarVisible; - property @Deprecated public default boolean isSystemBarsVisible; - property @Deprecated public abstract boolean navigationBarDarkContentEnabled; - property @Deprecated public abstract boolean statusBarDarkContentEnabled; - property @Deprecated public abstract int systemBarsBehavior; - property @Deprecated public default boolean systemBarsDarkContentEnabled; - } - - public final class SystemUiControllerKt { - method @Deprecated @androidx.compose.runtime.Composable public static com.google.accompanist.systemuicontroller.SystemUiController rememberSystemUiController(optional android.view.Window? window); - } - -} - diff --git a/systemuicontroller/build.gradle.kts b/systemuicontroller/build.gradle.kts deleted file mode 100644 index 1c0b4717d..000000000 --- a/systemuicontroller/build.gradle.kts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -@file:Suppress("UnstableApiUsage") - -plugins { - alias(libs.plugins.accompanist.android.library) - alias(libs.plugins.accompanist.android.library.compose) - alias(libs.plugins.accompanist.android.library.published) -} - -android { - namespace = "com.google.accompanist.systemuicontroller" - - testOptions { - unitTests.all { - it.useJUnit { - excludeCategories("com.google.accompanist.internal.test.IgnoreOnRobolectric") - } - } - } - - sourceSets { - named("test") { - java.srcDirs("src/sharedTest/kotlin") - res.srcDirs("src/sharedTest/res") - } - named("androidTest") { - java.srcDirs("src/sharedTest/kotlin") - res.srcDirs("src/sharedTest/res") - } - } -} - -dependencies { - implementation(libs.androidx.core) - implementation(libs.compose.ui.ui) - implementation(libs.kotlin.coroutines.android) - - // ====================== - // Test dependencies - // ====================== - - androidTestImplementation(project(":internal-testutils")) - testImplementation(project(":internal-testutils")) - - androidTestImplementation(libs.junit) - testImplementation(libs.junit) - - androidTestImplementation(libs.truth) - testImplementation(libs.truth) - - androidTestImplementation(libs.compose.ui.test.junit4) - testImplementation(libs.compose.ui.test.junit4) - - androidTestImplementation(libs.compose.ui.test.manifest) - testImplementation(libs.compose.ui.test.manifest) - - androidTestImplementation(libs.androidx.test.runner) - testImplementation(libs.androidx.test.runner) - - testImplementation(libs.robolectric) -} diff --git a/systemuicontroller/gradle.properties b/systemuicontroller/gradle.properties deleted file mode 100644 index 45fe13808..000000000 --- a/systemuicontroller/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -POM_ARTIFACT_ID=accompanist-systemuicontroller -POM_NAME=Accompanist System UI Controller library -POM_PACKAGING=aar \ No newline at end of file diff --git a/systemuicontroller/src/main/AndroidManifest.xml b/systemuicontroller/src/main/AndroidManifest.xml deleted file mode 100644 index 928e8bf1f..000000000 --- a/systemuicontroller/src/main/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt b/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt deleted file mode 100644 index acc1a1d4a..000000000 --- a/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.systemuicontroller - -import android.app.Activity -import android.content.Context -import android.content.ContextWrapper -import android.os.Build -import android.view.View -import android.view.Window -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import androidx.compose.runtime.remember -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.window.DialogWindowProvider -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat - -/** - * A class which provides easy-to-use utilities for updating the System UI bar - * colors within Jetpack Compose. - * - * @sample com.google.accompanist.sample.systemuicontroller.SystemUiControllerSample - */ -@Deprecated( - """ -accompanist/systemuicontroller is deprecated and the API is no longer maintained. -We recommend going edge to edge using Activity.enableEdgeToEdge in androidx.activity. -For more information please visit https://google.github.io/accompanist/systemuicontroller -""" -) -@Stable -public interface SystemUiController { - - /** - * Control for the behavior of the system bars. This value should be one of the - * [WindowInsetsControllerCompat] behavior constants: - * [WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH] (Deprecated), - * [WindowInsetsControllerCompat.BEHAVIOR_DEFAULT] and - * [WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE]. - */ - public var systemBarsBehavior: Int - - /** - * Property which holds the status bar visibility. If set to true, show the status bar, - * otherwise hide the status bar. - */ - public var isStatusBarVisible: Boolean - - /** - * Property which holds the navigation bar visibility. If set to true, show the navigation bar, - * otherwise hide the navigation bar. - */ - public var isNavigationBarVisible: Boolean - - /** - * Property which holds the status & navigation bar visibility. If set to true, show both bars, - * otherwise hide both bars. - */ - public var isSystemBarsVisible: Boolean - get() = isNavigationBarVisible && isStatusBarVisible - set(value) { - isStatusBarVisible = value - isNavigationBarVisible = value - } - - /** - * Set the status bar color. - * - * @param color The **desired** [Color] to set. This may require modification if running on an - * API level that only supports white status bar icons. - * @param darkIcons Whether dark status bar icons would be preferable. - * @param transformColorForLightContent A lambda which will be invoked to transform [color] if - * dark icons were requested but are not available. Defaults to applying a black scrim. - * - * @see statusBarDarkContentEnabled - */ - public fun setStatusBarColor( - color: Color, - darkIcons: Boolean = color.luminance() > 0.5f, - transformColorForLightContent: (Color) -> Color = BlackScrimmed - ) - - /** - * Set the navigation bar color. - * - * @param color The **desired** [Color] to set. This may require modification if running on an - * API level that only supports white navigation bar icons. Additionally this will be ignored - * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the - * system UI automatically applies background protection in other navigation modes. - * @param darkIcons Whether dark navigation bar icons would be preferable. - * @param navigationBarContrastEnforced Whether the system should ensure that the navigation - * bar has enough contrast when a fully transparent background is requested. Only supported on - * API 29+. - * @param transformColorForLightContent A lambda which will be invoked to transform [color] if - * dark icons were requested but are not available. Defaults to applying a black scrim. - * - * @see navigationBarDarkContentEnabled - * @see navigationBarContrastEnforced - */ - public fun setNavigationBarColor( - color: Color, - darkIcons: Boolean = color.luminance() > 0.5f, - navigationBarContrastEnforced: Boolean = true, - transformColorForLightContent: (Color) -> Color = BlackScrimmed - ) - - /** - * Set the status and navigation bars to [color]. - * - * @see setStatusBarColor - * @see setNavigationBarColor - */ - public fun setSystemBarsColor( - color: Color, - darkIcons: Boolean = color.luminance() > 0.5f, - isNavigationBarContrastEnforced: Boolean = true, - transformColorForLightContent: (Color) -> Color = BlackScrimmed - ) { - setStatusBarColor(color, darkIcons, transformColorForLightContent) - setNavigationBarColor( - color, - darkIcons, - isNavigationBarContrastEnforced, - transformColorForLightContent - ) - } - - /** - * Property which holds whether the status bar icons + content are 'dark' or not. - */ - public var statusBarDarkContentEnabled: Boolean - - /** - * Property which holds whether the navigation bar icons + content are 'dark' or not. - */ - public var navigationBarDarkContentEnabled: Boolean - - /** - * Property which holds whether the status & navigation bar icons + content are 'dark' or not. - */ - public var systemBarsDarkContentEnabled: Boolean - get() = statusBarDarkContentEnabled && navigationBarDarkContentEnabled - set(value) { - statusBarDarkContentEnabled = value - navigationBarDarkContentEnabled = value - } - - /** - * Property which holds whether the system is ensuring that the navigation bar has enough - * contrast when a fully transparent background is requested. Only has an affect when running - * on Android API 29+ devices. - */ - public var isNavigationBarContrastEnforced: Boolean -} - -/** - * Remembers a [SystemUiController] for the given [window]. - * - * If no [window] is provided, an attempt to find the correct [Window] is made. - * - * First, if the [LocalView]'s parent is a [DialogWindowProvider], then that dialog's [Window] will - * be used. - * - * Second, we attempt to find [Window] for the [Activity] containing the [LocalView]. - * - * If none of these are found (such as may happen in a preview), then the functionality of the - * returned [SystemUiController] will be degraded, but won't throw an exception. - */ -@Deprecated( - """ -accompanist/systemuicontroller is deprecated and the API is no longer maintained. -We recommend going edge to edge using EdgeToEdge.enableEdgeToEdge in androidx.activity. -For more information please visit https://google.github.io/accompanist/systemuicontroller -""" -) -@Composable -public fun rememberSystemUiController( - window: Window? = findWindow(), -): SystemUiController { - val view = LocalView.current - return remember(view, window) { AndroidSystemUiController(view, window) } -} - -@Composable -private fun findWindow(): Window? = - (LocalView.current.parent as? DialogWindowProvider)?.window - ?: LocalView.current.context.findWindow() - -private tailrec fun Context.findWindow(): Window? = - when (this) { - is Activity -> window - is ContextWrapper -> baseContext.findWindow() - else -> null - } - -/** - * A helper class for setting the navigation and status bar colors for a [View], gracefully - * degrading behavior based upon API level. - * - * Typically you would use [rememberSystemUiController] to remember an instance of this. - */ -internal class AndroidSystemUiController( - private val view: View, - private val window: Window? -) : SystemUiController { - private val windowInsetsController = window?.let { - WindowCompat.getInsetsController(it, view) - } - - override fun setStatusBarColor( - color: Color, - darkIcons: Boolean, - transformColorForLightContent: (Color) -> Color - ) { - statusBarDarkContentEnabled = darkIcons - - window?.statusBarColor = when { - darkIcons && windowInsetsController?.isAppearanceLightStatusBars != true -> { - // If we're set to use dark icons, but our windowInsetsController call didn't - // succeed (usually due to API level), we instead transform the color to maintain - // contrast - transformColorForLightContent(color) - } - else -> color - }.toArgb() - } - - override fun setNavigationBarColor( - color: Color, - darkIcons: Boolean, - navigationBarContrastEnforced: Boolean, - transformColorForLightContent: (Color) -> Color - ) { - navigationBarDarkContentEnabled = darkIcons - isNavigationBarContrastEnforced = navigationBarContrastEnforced - - window?.navigationBarColor = when { - darkIcons && windowInsetsController?.isAppearanceLightNavigationBars != true -> { - // If we're set to use dark icons, but our windowInsetsController call didn't - // succeed (usually due to API level), we instead transform the color to maintain - // contrast - transformColorForLightContent(color) - } - else -> color - }.toArgb() - } - - override var systemBarsBehavior: Int - get() = windowInsetsController?.systemBarsBehavior ?: 0 - set(value) { - windowInsetsController?.systemBarsBehavior = value - } - - override var isStatusBarVisible: Boolean - get() { - return ViewCompat.getRootWindowInsets(view) - ?.isVisible(WindowInsetsCompat.Type.statusBars()) == true - } - set(value) { - if (value) { - windowInsetsController?.show(WindowInsetsCompat.Type.statusBars()) - } else { - windowInsetsController?.hide(WindowInsetsCompat.Type.statusBars()) - } - } - - override var isNavigationBarVisible: Boolean - get() { - return ViewCompat.getRootWindowInsets(view) - ?.isVisible(WindowInsetsCompat.Type.navigationBars()) == true - } - set(value) { - if (value) { - windowInsetsController?.show(WindowInsetsCompat.Type.navigationBars()) - } else { - windowInsetsController?.hide(WindowInsetsCompat.Type.navigationBars()) - } - } - - override var statusBarDarkContentEnabled: Boolean - get() = windowInsetsController?.isAppearanceLightStatusBars == true - set(value) { - windowInsetsController?.isAppearanceLightStatusBars = value - } - - override var navigationBarDarkContentEnabled: Boolean - get() = windowInsetsController?.isAppearanceLightNavigationBars == true - set(value) { - windowInsetsController?.isAppearanceLightNavigationBars = value - } - - override var isNavigationBarContrastEnforced: Boolean - get() = Build.VERSION.SDK_INT >= 29 && window?.isNavigationBarContrastEnforced == true - set(value) { - if (Build.VERSION.SDK_INT >= 29) { - window?.isNavigationBarContrastEnforced = value - } - } -} - -private val BlackScrim = Color(0f, 0f, 0f, 0.3f) // 30% opaque black -private val BlackScrimmed: (Color) -> Color = { original -> - BlackScrim.compositeOver(original) -} diff --git a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivityRememberSystemUiControllerTest.kt b/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivityRememberSystemUiControllerTest.kt deleted file mode 100644 index f90ed7ad4..000000000 --- a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivityRememberSystemUiControllerTest.kt +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.systemuicontroller - -import android.os.Build -import android.view.View -import android.view.Window -import androidx.activity.ComponentActivity -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.test.junit4.createAndroidComposeRule -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.FlakyTest -import androidx.test.filters.SdkSuppress -import com.google.accompanist.internal.test.IgnoreOnRobolectric -import com.google.accompanist.internal.test.waitUntil -import com.google.accompanist.internal.test.withActivity -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.experimental.categories.Category -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class ActivityRememberSystemUiControllerTest { - @get:Rule - val rule = createAndroidComposeRule() - - private lateinit var window: Window - private lateinit var contentView: View - - @Before - fun setup() { - window = rule.activityRule.scenario.withActivity { it.window } - contentView = rule.activityRule.scenario.withActivity { - it.findViewById(android.R.id.content)!! - } - - if (Build.VERSION.SDK_INT >= 29) { - // On API 29+, the system can modify the bar colors to maintain contrast. - // We disable that here to make it simple to assert expected values - rule.activityRule.scenario.onActivity { - window.apply { - isNavigationBarContrastEnforced = false - isStatusBarContrastEnforced = false - } - } - } - } - - @Test - fun statusBarColor() { - rule.setContent { - // Create an systemUiController and set the status bar color - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.Blue, darkIcons = false) - } - } - - // Assert that the color was set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Blue) - } - - @Test - fun navigationBarColor() { - rule.setContent { - // Now create an systemUiController and set the navigation bar color - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.Green, darkIcons = false) - } - } - - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Green) - } - - @Test - fun systemBarColor() { - rule.setContent { - // Now create an systemUiController and set the system bar colors - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setSystemBarsColor(Color.Red, darkIcons = false) - } - } - - // Assert that the colors were set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 23+ - @SdkSuppress(maxSdkVersion = 22) - fun statusBarIcons_scrim() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 23) - fun statusBarIcons_native() { - // Now create an systemUiController and set the status bar with dark icons - rule.setContent { - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.statusBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isTrue() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 25+ - @SdkSuppress(maxSdkVersion = 25) - fun navigationBarIcons_scrim() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 26) - fun navigationBar_native() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isTrue() - } - } - - @Test - @SdkSuppress(minSdkVersion = 29) - fun navigationBar_contrastEnforced() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - rule.activityRule.scenario.onActivity { - // Assert that the contrast is not enforced initially - assertThat(systemUiController.isNavigationBarContrastEnforced).isFalse() - - // and set the navigation bar with dark icons and enforce contrast - systemUiController.setNavigationBarColor( - Color.Transparent, - darkIcons = true, - navigationBarContrastEnforced = true - ) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Transparent) - - // Assert that the system applied the contrast enforced property - assertThat(window.isNavigationBarContrastEnforced).isTrue() - - // Assert that the controller reflects that the contrast is enforced - assertThat(systemUiController.isNavigationBarContrastEnforced).isTrue() - } - } - - @Suppress("DEPRECATION") - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsByTouch() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsBySwipe() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_DEFAULT - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showTransientBarsBySwipe() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun statusBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isStatusBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isStatusBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun navigationBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isNavigationBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isNavigationBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - fun systemBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - systemUiController = rememberSystemUiController() - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isSystemBarsVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isSystemBarsVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - private fun isRootWindowTypeVisible(type: Int): Boolean { - return rule.activityRule.scenario.withActivity { - ViewCompat.getRootWindowInsets(contentView)!!.isVisible(type) - } - } -} diff --git a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivitySystemUiControllerTest.kt b/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivitySystemUiControllerTest.kt deleted file mode 100644 index 58cf21ad3..000000000 --- a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/ActivitySystemUiControllerTest.kt +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.systemuicontroller - -import android.os.Build -import android.view.View -import android.view.Window -import androidx.activity.ComponentActivity -import androidx.compose.ui.graphics.Color -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.test.ext.junit.rules.ActivityScenarioRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.FlakyTest -import androidx.test.filters.SdkSuppress -import com.google.accompanist.internal.test.IgnoreOnRobolectric -import com.google.accompanist.internal.test.waitUntil -import com.google.accompanist.internal.test.withActivity -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.experimental.categories.Category -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class ActivitySystemUiControllerTest { - @get:Rule - val rule = ActivityScenarioRule(ComponentActivity::class.java) - - private lateinit var window: Window - private lateinit var contentView: View - - @Before - fun setup() { - window = rule.scenario.withActivity { it.window } - contentView = rule.scenario.withActivity { it.findViewById(android.R.id.content)!! } - - if (Build.VERSION.SDK_INT >= 29) { - // On API 29+, the system can modify the bar colors to maintain contrast. - // We disable that here to make it simple to assert expected values - rule.scenario.onActivity { - window.apply { - isNavigationBarContrastEnforced = false - isStatusBarContrastEnforced = false - } - } - } - } - - @Test - fun statusBarColor() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() and set the status bar color - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.Blue, darkIcons = false) - } - - // Assert that the color was set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Blue) - } - - @Test - fun navigationBarColor() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() and set the status bar color - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.Green, darkIcons = false) - } - - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Green) - } - - @Test - fun systemBarColor() { - // Now create an AndroidSystemUiController() and set the system bar colors - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setSystemBarsColor(Color.Red, darkIcons = false) - } - - // Assert that the colors were set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 23+ - @SdkSuppress(maxSdkVersion = 22) - fun statusBarIcons_scrim() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 23) - fun statusBarIcons_native() { - // Now create an AndroidSystemUiController() and set the status bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.statusBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isTrue() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 25+ - @SdkSuppress(maxSdkVersion = 25) - fun navigationBarIcons_scrim() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 26) - fun navigationBar_native() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isTrue() - } - } - - @Test - @SdkSuppress(minSdkVersion = 29) - fun navigationBar_contrastEnforced() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() - val controller = AndroidSystemUiController(contentView, window) - - // Assert that the contrast is not enforced initially - assertThat(controller.isNavigationBarContrastEnforced).isFalse() - - // and set the navigation bar with dark icons and enforce contrast - controller.setNavigationBarColor( - Color.Transparent, - darkIcons = true, - navigationBarContrastEnforced = true - ) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Transparent) - - // Assert that the system applied the contrast enforced property - assertThat(window.isNavigationBarContrastEnforced).isTrue() - - // Assert that the controller reflects that the contrast is enforced - assertThat(controller.isNavigationBarContrastEnforced).isTrue() - } - } - - @Suppress("DEPRECATION") - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsByTouch() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsBySwipe() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showTransientBarsBySwipe() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun statusBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isStatusBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isStatusBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun navigationBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isNavigationBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isNavigationBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - fun systemBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isSystemBarsVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isSystemBarsVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - private fun isRootWindowTypeVisible(type: Int): Boolean { - return rule.scenario.withActivity { - ViewCompat.getRootWindowInsets(contentView)!!.isVisible(type) - } - } -} diff --git a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogRememberSystemUiControllerTest.kt b/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogRememberSystemUiControllerTest.kt deleted file mode 100644 index 72c7594a4..000000000 --- a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogRememberSystemUiControllerTest.kt +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.systemuicontroller - -import android.os.Build -import android.view.View -import android.view.Window -import androidx.activity.ComponentActivity -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.test.junit4.createAndroidComposeRule -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogWindowProvider -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.FlakyTest -import androidx.test.filters.SdkSuppress -import com.google.accompanist.internal.test.IgnoreOnRobolectric -import com.google.accompanist.internal.test.waitUntil -import com.google.accompanist.internal.test.withActivity -import com.google.accompanist.systemuicontroller.test.R -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.experimental.categories.Category -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class DialogRememberSystemUiControllerTest { - @get:Rule - val rule = createAndroidComposeRule() - - private lateinit var window: Window - private lateinit var contentView: View - - @Before - fun setup() { - rule.activityRule.scenario.onActivity { - it.setTheme(R.style.DialogSystemUiControllerTheme) - } - } - - @Test - fun statusBarColor() { - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - - // Create an systemUiController and set the status bar color - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.Blue, darkIcons = false) - } - } - } - - // Assert that the color was set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Blue) - } - - @Test - fun navigationBarColor() { - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - - // Now create an systemUiController and set the navigation bar color - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.Green, darkIcons = false) - } - } - } - - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Green) - } - - @Test - fun systemBarColor() { - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - - // Now create an systemUiController and set the system bar colors - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setSystemBarsColor(Color.Red, darkIcons = false) - } - } - } - - // Assert that the colors were set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 23+ - @SdkSuppress(maxSdkVersion = 22) - fun statusBarIcons_scrim() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isFalse() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @SdkSuppress(minSdkVersion = 23) - fun statusBarIcons_native() { - // Now create an systemUiController and set the status bar with dark icons - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.statusBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isTrue() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 25+ - @SdkSuppress(maxSdkVersion = 25) - fun navigationBarIcons_scrim() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isFalse() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @SdkSuppress(minSdkVersion = 26) - fun navigationBar_native() { - // Now create an systemUiController and set the navigation bar with dark icons - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - val systemUiController = rememberSystemUiController() - SideEffect { - systemUiController.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.activityRule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isTrue() - } - } - - @Test - @SdkSuppress(minSdkVersion = 29) - fun navigationBar_contrastEnforced() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - - systemUiController = rememberSystemUiController() - } - } - - if (Build.VERSION.SDK_INT >= 29) { - // On API 29+, the system can modify the bar colors to maintain contrast. - // We disable that here to make it simple to assert expected values - rule.activityRule.scenario.onActivity { - window.apply { - isNavigationBarContrastEnforced = false - isStatusBarContrastEnforced = false - } - } - } - - rule.activityRule.scenario.onActivity { - // Assert that the contrast is not enforced initially - assertThat(systemUiController.isNavigationBarContrastEnforced).isFalse() - - // and set the navigation bar with dark icons and enforce contrast - systemUiController.setNavigationBarColor( - Color.Transparent, - darkIcons = true, - navigationBarContrastEnforced = true - ) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Transparent) - - // Assert that the system applied the contrast enforced property - assertThat(window.isNavigationBarContrastEnforced).isTrue() - - // Assert that the controller reflects that the contrast is enforced - assertThat(systemUiController.isNavigationBarContrastEnforced).isTrue() - } - } - - @Suppress("DEPRECATION") - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsByTouch() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsBySwipe() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_DEFAULT - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showTransientBarsBySwipe() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - window = (LocalView.current.parent as DialogWindowProvider).window - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - rule.activityRule.scenario.onActivity { - systemUiController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun statusBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isStatusBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isStatusBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun navigationBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isNavigationBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isNavigationBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - fun systemBarsVisibility() { - lateinit var systemUiController: SystemUiController - - rule.setContent { - Dialog(onDismissRequest = {}) { - contentView = LocalView.current - - systemUiController = rememberSystemUiController() - } - } - - // First show the bars - rule.activityRule.scenario.onActivity { - systemUiController.isSystemBarsVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.activityRule.scenario.onActivity { - systemUiController.isSystemBarsVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - private fun isRootWindowTypeVisible(type: Int): Boolean { - return rule.activityRule.scenario.withActivity { - ViewCompat.getRootWindowInsets(contentView)!!.isVisible(type) - } - } -} diff --git a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogSystemUiControllerTest.kt b/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogSystemUiControllerTest.kt deleted file mode 100644 index eb6eab27b..000000000 --- a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/DialogSystemUiControllerTest.kt +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("DEPRECATION") - -package com.google.accompanist.systemuicontroller - -import android.app.Dialog -import android.os.Build -import android.os.Bundle -import android.view.View -import android.view.Window -import android.widget.FrameLayout -import androidx.activity.ComponentActivity -import androidx.compose.ui.graphics.Color -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat -import androidx.test.ext.junit.rules.ActivityScenarioRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.FlakyTest -import androidx.test.filters.SdkSuppress -import com.google.accompanist.internal.test.IgnoreOnRobolectric -import com.google.accompanist.internal.test.waitUntil -import com.google.accompanist.internal.test.withActivity -import com.google.accompanist.systemuicontroller.test.R -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.experimental.categories.Category -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class DialogSystemUiControllerTest { - @get:Rule - val rule = ActivityScenarioRule(ComponentActivity::class.java) - - private lateinit var window: Window - private lateinit var contentView: View - - @Before - fun setup() { - contentView = rule.scenario.withActivity { FrameLayout(it) } - - rule.scenario.onActivity { - it.setTheme(R.style.DialogSystemUiControllerTheme) - - object : Dialog(it) { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(contentView) - } - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - this@DialogSystemUiControllerTest.window = window!! - } - }.show() - } - - if (Build.VERSION.SDK_INT >= 29) { - // On API 29+, the system can modify the bar colors to maintain contrast. - // We disable that here to make it simple to assert expected values - rule.scenario.onActivity { - window.apply { - isNavigationBarContrastEnforced = false - isStatusBarContrastEnforced = false - } - } - } - } - - @Test - fun statusBarColor() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() and set the status bar color - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.Blue, darkIcons = false) - } - - // Assert that the color was set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Blue) - } - - @Test - fun navigationBarColor() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() and set the status bar color - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.Green, darkIcons = false) - } - - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Green) - } - - @Test - fun systemBarColor() { - // Now create an AndroidSystemUiController() and set the system bar colors - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setSystemBarsColor(Color.Red, darkIcons = false) - } - - // Assert that the colors were set - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 23+ - @SdkSuppress(maxSdkVersion = 22) - fun statusBarIcons_scrim() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.statusBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 23) - fun statusBarIcons_native() { - // Now create an AndroidSystemUiController() and set the status bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setStatusBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.statusBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightStatusBars).isTrue() - } - } - - @Test - @Category(IgnoreOnRobolectric::class) // Robolectric implements the new behavior from 25+ - @SdkSuppress(maxSdkVersion = 25) - fun navigationBarIcons_scrim() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were set to our 'darkened' color - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Red) - - // Assert that the system couldn't apply the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isFalse() - } - } - - @Test - @SdkSuppress(minSdkVersion = 26) - fun navigationBar_native() { - // Now create an AndroidSystemUiController() and set the navigation bar with dark icons - rule.scenario.onActivity { - val controller = AndroidSystemUiController(contentView, window) - controller.setNavigationBarColor(Color.White, darkIcons = true) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.White) - - // Assert that the system applied the native light icons - rule.scenario.onActivity { - val windowInsetsController = WindowCompat.getInsetsController(window, contentView) - assertThat(windowInsetsController.isAppearanceLightNavigationBars).isTrue() - } - } - - @Test - @SdkSuppress(minSdkVersion = 29) - fun navigationBar_contrastEnforced() { - rule.scenario.onActivity { - // Now create an AndroidSystemUiController() - val controller = AndroidSystemUiController(contentView, window) - - // Assert that the contrast is not enforced initially - assertThat(controller.isNavigationBarContrastEnforced).isFalse() - - // and set the navigation bar with dark icons and enforce contrast - controller.setNavigationBarColor( - Color.Transparent, - darkIcons = true, - navigationBarContrastEnforced = true - ) { - // Here we can provide custom logic to 'darken' the color to maintain contrast. - // We return red just to assert below. - Color.Red - } - - // Assert that the colors were darkened color is not used - assertThat(Color(window.navigationBarColor)).isEqualTo(Color.Transparent) - - // Assert that the system applied the contrast enforced property - assertThat(window.isNavigationBarContrastEnforced).isTrue() - - // Assert that the controller reflects that the contrast is enforced - assertThat(controller.isNavigationBarContrastEnforced).isTrue() - } - } - - @Suppress("DEPRECATION") - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsByTouch() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showBarsBySwipe() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_DEFAULT - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT) - } - - @Test - @SdkSuppress(minSdkVersion = 30) // TODO: https://issuetracker.google.com/issues/189366125 - fun systemBarsBehavior_showTransientBarsBySwipe() { - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - rule.scenario.onActivity { - controller.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - - assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior) - .isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun statusBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isStatusBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isStatusBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - @Test - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - @Category(IgnoreOnRobolectric::class) - fun navigationBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isNavigationBarVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isNavigationBarVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - } - - @Test - @Category(IgnoreOnRobolectric::class) - @FlakyTest(detail = "https://github.com/google/accompanist/issues/491") - @SdkSuppress(minSdkVersion = 23) // rootWindowInsets which work - fun systemBarsVisibility() { - // Now create an AndroidSystemUiController() and set the system bar colors - val controller = rule.scenario.withActivity { - AndroidSystemUiController(contentView, window) - } - - // First show the bars - rule.scenario.onActivity { - controller.isSystemBarsVisible = true - } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - - // Now hide the bars - rule.scenario.onActivity { - controller.isSystemBarsVisible = false - } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.navigationBars()) } - waitUntil { !isRootWindowTypeVisible(WindowInsetsCompat.Type.statusBars()) } - } - - private fun isRootWindowTypeVisible(type: Int): Boolean { - return rule.scenario.withActivity { - ViewCompat.getRootWindowInsets(contentView)!!.isVisible(type) - } - } -} diff --git a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/FakeTests.kt b/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/FakeTests.kt deleted file mode 100644 index 7fdab0325..000000000 --- a/systemuicontroller/src/sharedTest/kotlin/com/google/accompanist/systemuicontroller/FakeTests.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.accompanist.systemuicontroller - -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 - -/** - * Fake tests to help with sharding: https://github.com/android/android-test/issues/973 - */ -@RunWith(JUnit4::class) -class FakeTests { - @Test - fun fake1() = Unit - - @Test - fun fake2() = Unit - - @Test - fun fake3() = Unit - - @Test - fun fake4() = Unit - - @Test - fun fake5() = Unit - - @Test - fun fake6() = Unit - - @Test - fun fake7() = Unit - - @Test - fun fake8() = Unit - - @Test - fun fake9() = Unit - - @Test - fun fake10() = Unit -} diff --git a/systemuicontroller/src/sharedTest/res/values/themes.xml b/systemuicontroller/src/sharedTest/res/values/themes.xml deleted file mode 100644 index 07fbd8d38..000000000 --- a/systemuicontroller/src/sharedTest/res/values/themes.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/systemuicontroller/src/test/resources/robolectric.properties b/systemuicontroller/src/test/resources/robolectric.properties deleted file mode 100644 index 2806eaffa..000000000 --- a/systemuicontroller/src/test/resources/robolectric.properties +++ /dev/null @@ -1,3 +0,0 @@ -# Pin SDK to 30 since Robolectric does not currently support API 31: -# https://github.com/robolectric/robolectric/issues/6635 -sdk=30