Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SystemUiController] Add support for systemBarsBehavior #1251

Merged
merged 1 commit into from Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -20,22 +20,31 @@ 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 com.google.accompanist.pager.ExperimentalPagerApi
import androidx.core.view.WindowInsetsControllerCompat
import com.google.accompanist.sample.AccompanistSampleTheme
import com.google.accompanist.sample.R
import com.google.accompanist.systemuicontroller.rememberSystemUiController
Expand All @@ -54,7 +63,6 @@ class SystemBarsVisibilitySample : ComponentActivity() {
}
}

@OptIn(ExperimentalPagerApi::class)
@Composable
private fun Sample() {
// Get the current SystemUiController
Expand All @@ -69,10 +77,61 @@ private fun Sample() {
modifier = Modifier.fillMaxSize()
) { padding ->
Column(
modifier = Modifier.fillMaxSize().padding(padding),
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_SHOW_BARS_BY_TOUCH
isShowingDropdownMenu = false
}
) {
Text("BEHAVIOR_SHOW_BARS_BY_TOUCH")
}
DropdownMenuItem(
onClick = {
systemUiController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
isShowingDropdownMenu = false
}
) {
Text("BEHAVIOR_SHOW_BARS_BY_SWIPE")
}
DropdownMenuItem(
onClick = {
systemUiController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
isShowingDropdownMenu = false
}
) {
Text("BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE")
}
}
}

/** Status bar */

Button(
Expand Down
3 changes: 3 additions & 0 deletions systemuicontroller/api/current.api
Expand Up @@ -4,6 +4,7 @@ package com.google.accompanist.systemuicontroller {
@androidx.compose.runtime.Stable public interface SystemUiController {
method public boolean getNavigationBarDarkContentEnabled();
method public boolean getStatusBarDarkContentEnabled();
method public int getSystemBarsBehavior();
method public default boolean getSystemBarsDarkContentEnabled();
method public boolean isNavigationBarContrastEnforced();
method public boolean isNavigationBarVisible();
Expand All @@ -16,6 +17,7 @@ package com.google.accompanist.systemuicontroller {
method public void setStatusBarColor(long color, optional boolean darkIcons, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color> transformColorForLightContent);
method public void setStatusBarDarkContentEnabled(boolean statusBarDarkContentEnabled);
method public void setStatusBarVisible(boolean isStatusBarVisible);
method public void setSystemBarsBehavior(int systemBarsBehavior);
method public default void setSystemBarsColor(long color, optional boolean darkIcons, optional boolean isNavigationBarContrastEnforced, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color> transformColorForLightContent);
method public default void setSystemBarsDarkContentEnabled(boolean value);
method public default void setSystemBarsVisible(boolean value);
Expand All @@ -25,6 +27,7 @@ package com.google.accompanist.systemuicontroller {
property public default boolean isSystemBarsVisible;
property public abstract boolean navigationBarDarkContentEnabled;
property public abstract boolean statusBarDarkContentEnabled;
property public abstract int systemBarsBehavior;
property public default boolean systemBarsDarkContentEnabled;
}

Expand Down
Expand Up @@ -34,6 +34,7 @@ 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
Expand All @@ -44,6 +45,15 @@ import androidx.core.view.WindowInsetsCompat
@Stable
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],
* [WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE] and
* [WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE].
*/
var systemBarsBehavior: Int

/**
* Property which holds the status bar visibility. If set to true, show the status bar,
* otherwise hide the status bar.
Expand Down Expand Up @@ -242,6 +252,12 @@ internal class AndroidSystemUiController(
}.toArgb()
}

override var systemBarsBehavior: Int
get() = windowInsetsController?.systemBarsBehavior ?: 0
set(value) {
windowInsetsController?.systemBarsBehavior = value
}

override var isStatusBarVisible: Boolean
get() {
return ViewCompat.getRootWindowInsets(view)
Expand Down
Expand Up @@ -26,6 +26,7 @@ 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
Expand Down Expand Up @@ -245,6 +246,60 @@ class ActivityRememberSystemUiControllerTest {
}
}

@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_SHOW_BARS_BY_SWIPE
}

assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior)
.isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE)
}

@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
Expand Down
Expand Up @@ -24,6 +24,7 @@ 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
Expand Down Expand Up @@ -225,6 +226,52 @@ class ActivitySystemUiControllerTest {
}
}

@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_SHOW_BARS_BY_SWIPE
}

assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior)
.isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE)
}

@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
Expand Down
Expand Up @@ -29,6 +29,7 @@ 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
Expand Down Expand Up @@ -286,6 +287,75 @@ class DialogRememberSystemUiControllerTest {
}
}

@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_SHOW_BARS_BY_SWIPE
}

assertThat(WindowCompat.getInsetsController(window, contentView).systemBarsBehavior)
.isEqualTo(WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE)
}

@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
Expand Down