我正在try 将edge to edge效果应用于Compose Material 3,但system navigation bar在某些设备上变得更暗.

可组合主题:

@Composable
fun AppTheme(
    systemUiController: SystemUiController = rememberSystemUiController(),
    useDarkColors: Boolean = isSystemInDarkTheme(),
    enableDynamicColors: Boolean = true,
    content: @Composable () -> Unit
) {
    val colorScheme = when {
        enableDynamicColors && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ->
            if (useDarkColors) dynamicDarkColorScheme(LocalContext.current)
            else dynamicLightColorScheme(LocalContext.current)

        useDarkColors -> darkColorScheme()

        else -> lightColorScheme()
    }

    DisposableEffect(key1 = Unit) {
        systemUiController.setSystemBarsColor(
            color = Color.Transparent,
            darkIcons = colorScheme.background.luminance() > 0.5
        )

        onDispose { }
    }

    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography(),
        shapes = Shapes(),
        content = content
    )
}

在上面的代码中,我将条定义为透明,并且只有当背景 colored颜色 亮度高于特定值时,图标才应该是暗的.

OBS:SystemUiController来自Accompanist System UI Controller个图书馆.

在hemes.xml中:

<style name="AppTheme" parent="android:Theme.Material.NoActionBar">
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:navigationBarColor">@android:color/transparent</item>
</style>

主要可合成内容:

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)

        setContent {
            val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()

            AppTheme {
                Scaffold(
                    modifier = Modifier
                        .fillMaxSize()
                        .nestedScroll(connection = scrollBehavior.nestedScrollConnection),
                    topBar = {
                        CenterAlignedTopAppBar(
                            modifier = Modifier.fillMaxWidth(),
                            title = { Text(text = "App Bar") },
                            scrollBehavior = scrollBehavior
                        )
                    },
                    bottomBar = {
                        NavigationBar(modifier = Modifier.fillMaxWidth()) {
                            repeat(times = 3) { index ->
                                NavigationBarItem(
                                    selected = index == 0,
                                    onClick = { },
                                    icon = {
                                        Icon(
                                            imageVector = Icons.Default.Home,
                                            contentDescription = null
                                        )
                                    },
                                    label = { Text(text = "Item $index") }
                                )
                            }
                        }
                    },
                    contentWindowInsets = WindowInsets.systemBars
                ) { contentPadding ->
                    LazyColumn(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(paddingValues = contentPadding),
                        contentPadding = PaddingValues(all = 16.dp),
                        verticalArrangement = Arrangement.spacedBy(space = 16.dp)
                    ) {
                        items(count = 50) { index ->
                            Text(text = "Item $index")
                        }
                    }
                }
            }
        }
    }
}

这里有一个简单的例子,说明system navigation bar变得更暗了.

system navigation bar是透明的,但由于某种原因,它应用了更暗的效果,因为NavigationBar.如果我们go 掉NavigationBar,我们将看到它通常遵循背景 colored颜色 ,无论它是带有动态 colored颜色 的浅色还是深色主题.

正如我在一开始所 comments 的,这个"问题"并不是在所有的设备上都会发生,在我的Android 12物理设备上,这个问题只会在轻量级主题时发生,在Android 13的模拟器上,无论主题是什么,问题都会发生.

例如,与Gmail app相比,系统导航栏保持与NavigationBar相同的 colored颜色 ,这是我想要的效果,而不是应用更暗的效果……

Problem when using NavigationBar: problem when using NavigationBar

Normal behavior without NavigationBar normal behavior without NavigationBar

Expected appearance with NavigationBar (from Gmail app) expected appearance with NavigationBar

推荐答案

发生此行为的原因是API级别29和更高级别上存在的功能.

从窗口类:

当请求完全透明的背景时,系统是否应确保导航栏具有足够的对比度.

从系统用户界面控制器库中:

当请求完全透明的背景时,系统是否确保导航栏具有足够的对比度.只有在Android API 29+设备上运行时才会产生影响.

如果您查看系统UI控制器库的setSystemBarsColor方法,您可以看到有isNavigationBarContrastEnforced来禁用此功能(默认情况下为启用).

此外,根据所使用的API的最低版本,可能无法使用暗图标,因此方法setSystemBarsColor在此场景中有transformColorForLightContent个参数,默认情况下,在此情况下将使用的 colored颜色 是30%不透明的黑色.

这样,您就可以按如下方式解决问题:

DisposableEffect(
    key1 = systemUiController,
    key2 = useDarkColors,
    key3 = enableDynamicColors
) {
    systemUiController.setSystemBarsColor(
        color = Color.Transparent,
        darkIcons = colorScheme.background.luminance() > 0.5,
        isNavigationBarContrastEnforced = false,
        // line below is optional, if you want to use any color
        // other than default black with 30% opacity:
        transformColorForLightContent = { Color.Black.copy(alpha = 0.7F) }
    )

    onDispose { }
}

需要注意的是,DisposableEffect需要接收键参数systemUiControlleruseDarkColorsenableDynamicColors,因为如果这些键中的任何一个发生变化,都应该重新应用效果.

Android相关问答推荐

如何使用单个代码库使用不同的firebase项目创建多个应用程序ID apk

Android Bundle getSerializable(String?):'可序列化?&# 39、被抛弃了在Java中被弃用

如何让用户与我的应用生成的多个音频文件交互

请求标头为空/无法通过拦截器获取

Jetpack Compose:带芯片的Textfield

从惰性列中删除项目时Jetpack Compose崩溃

如何修复Google Play市场中有关已删除广告库的错误消息?

如何使用其他组件的位置来定位自定义弹出窗口

如何在 compose android中将图像覆盖在另一个图像上

如何在Android Studio中删除项目

Jetpack Compose with Paging 3 发出太多网络请求

AttributionSource 需要 android.permission.BLUETOOTH_SCAN 权限的问题

PullRefreshIndicator 与 ScrollableTabRow 重叠

从 Firebase 云存储中获取照片会导致 Android Jetpack Compose 闪烁

Int 传递给 Intent 但Android工作室说我传递了一个字符串

记住或不记得derivedStateOf

如何在 Android Studio 中创建新的可组合函数?

如何在 Jetpack Compose 中禁用 TabRow 或 Tab 中的涟漪效应?

Android全屏AlertDialog

在使用 Retrofit 和 Room 时,我是否需要提及协程调度程序?