diff --git a/systemuicontroller/api/systemuicontroller.api b/systemuicontroller/api/systemuicontroller.api index ccac3f045..c4d11aa7b 100644 --- a/systemuicontroller/api/systemuicontroller.api +++ b/systemuicontroller/api/systemuicontroller.api @@ -1,24 +1,27 @@ public final class com/google/accompanist/systemuicontroller/AndroidSystemUiController : com/google/accompanist/systemuicontroller/SystemUiController { public static final field $stable I public fun (Landroid/view/View;)V - public fun setNavigationBarColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V + public fun isNavigationBarContrastEnforced ()Z + public fun setNavigationBarColor-Iv8Zu3U (JZZLkotlin/jvm/functions/Function1;)V public fun setStatusBarColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V - public fun setSystemBarsColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V + public fun setSystemBarsColor-Iv8Zu3U (JZZLkotlin/jvm/functions/Function1;)V } public abstract interface class com/google/accompanist/systemuicontroller/SystemUiController { - public abstract fun setNavigationBarColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V + public abstract fun isNavigationBarContrastEnforced ()Z + public abstract fun setNavigationBarColor-Iv8Zu3U (JZZLkotlin/jvm/functions/Function1;)V public abstract fun setStatusBarColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V - public abstract fun setSystemBarsColor-ek8zF_U (JZLkotlin/jvm/functions/Function1;)V + public abstract fun setSystemBarsColor-Iv8Zu3U (JZZLkotlin/jvm/functions/Function1;)V } public final class com/google/accompanist/systemuicontroller/SystemUiController$DefaultImpls { - public static fun setNavigationBarColor-ek8zF_U (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;)V - public static synthetic fun setNavigationBarColor-ek8zF_U$default (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static fun isNavigationBarContrastEnforced (Lcom/google/accompanist/systemuicontroller/SystemUiController;)Z + public static fun setNavigationBarColor-Iv8Zu3U (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZZLkotlin/jvm/functions/Function1;)V + public static synthetic fun setNavigationBarColor-Iv8Zu3U$default (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V public static fun setStatusBarColor-ek8zF_U (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;)V public static synthetic fun setStatusBarColor-ek8zF_U$default (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V - public static fun setSystemBarsColor-ek8zF_U (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;)V - public static synthetic fun setSystemBarsColor-ek8zF_U$default (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static fun setSystemBarsColor-Iv8Zu3U (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZZLkotlin/jvm/functions/Function1;)V + public static synthetic fun setSystemBarsColor-Iv8Zu3U$default (Lcom/google/accompanist/systemuicontroller/SystemUiController;JZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } public final class com/google/accompanist/systemuicontroller/SystemUiControllerKt { diff --git a/systemuicontroller/src/androidTest/java/com/google/accompanist/systemuicontroller/SystemUiControllerTest.kt b/systemuicontroller/src/androidTest/java/com/google/accompanist/systemuicontroller/SystemUiControllerTest.kt index 8905baa67..a82eedee2 100644 --- a/systemuicontroller/src/androidTest/java/com/google/accompanist/systemuicontroller/SystemUiControllerTest.kt +++ b/systemuicontroller/src/androidTest/java/com/google/accompanist/systemuicontroller/SystemUiControllerTest.kt @@ -183,6 +183,40 @@ class SystemUiControllerTest { val windowInsetsController = ViewCompat.getWindowInsetsController(view)!! assertThat(windowInsetsController.isAppearanceLightNavigationBars).isTrue() } + + @Test + @UiThreadTest + @SdkSuppress(minSdkVersion = 29) + fun navigationBar_contrastEnforced() { + val view = composeTestRule.contentView + val window = composeTestRule.activity.window + + // Now create an AndroidSystemUiController() + val controller = AndroidSystemUiController(view) + + // 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() + } } val AndroidComposeTestRule<*, *>.contentView diff --git a/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt b/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt index b21a6ccb1..8014862d4 100644 --- a/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt +++ b/systemuicontroller/src/main/java/com/google/accompanist/systemuicontroller/SystemUiController.kt @@ -19,6 +19,7 @@ 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 @@ -63,12 +64,16 @@ interface SystemUiController { * 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. */ fun setNavigationBarColor( color: Color, darkIcons: Boolean = color.luminance() > 0.5f, + navigationBarContrastEnforced: Boolean = true, transformColorForLightContent: (Color) -> Color = BlackScrimmed ) = Unit @@ -81,11 +86,25 @@ interface SystemUiController { fun setSystemBarsColor( color: Color, darkIcons: Boolean = color.luminance() > 0.5f, + isNavigationBarContrastEnforced: Boolean = true, transformColorForLightContent: (Color) -> Color = BlackScrimmed ) { setStatusBarColor(color, darkIcons, transformColorForLightContent) - setNavigationBarColor(color, darkIcons, transformColorForLightContent) + setNavigationBarColor( + color, + darkIcons, + isNavigationBarContrastEnforced, + transformColorForLightContent + ) } + + /** + * Returns whether the system is ensuring that the navigation bar has enough contrast when a + * fully transparent background is requested. + * + * @return true, if API is 29+ and the system is ensuring contrast, false otherwise. + */ + fun isNavigationBarContrastEnforced(): Boolean = false } /** @@ -129,6 +148,7 @@ class AndroidSystemUiController(view: View) : SystemUiController { override fun setNavigationBarColor( color: Color, darkIcons: Boolean, + navigationBarContrastEnforced: Boolean, transformColorForLightContent: (Color) -> Color ) { windowInsetsController?.isAppearanceLightNavigationBars = darkIcons @@ -142,6 +162,14 @@ class AndroidSystemUiController(view: View) : SystemUiController { } else -> color }.toArgb() + + if (Build.VERSION.SDK_INT >= 29) { + window?.isNavigationBarContrastEnforced = navigationBarContrastEnforced + } + } + + override fun isNavigationBarContrastEnforced(): Boolean { + return Build.VERSION.SDK_INT >= 29 && window?.isNavigationBarContrastEnforced == true } private fun Context.findWindow(): Window? {