Я новичок в Котлине. У меня есть BottomNavigation
, завернутый в Scaffold
. Изменение цвета фона вкладок работает хорошо. Но хотя значки на самом деле белые, в приложении они кажутся черными, хотя я установил selectedContentColor
на Color.White
.
И от unselectedContentColor
до Color.White.copy(alpha = 0.7f)
.
Он даже не показывает, нахожусь ли я на той или иной вкладке. Они все остаются прежними.
Это код в моем MainActivity.kt:
var selectedTab by remember { mutableIntStateOf(0) }
val tabs = listOf("Home", "Media", "Videos", "Contact")
val icons = listOf(
painterResource(id = R.drawable.ic_home),
painterResource(id = R.drawable.ic_media_link),
painterResource(id = R.drawable.ic_video_library),
painterResource(id = R.drawable.ic_account_circle),
)
Scaffold(
bottomBar = {
BottomNavigation(
backgroundColor = Color(0xff6c247c),
contentColor = Color.White,
) {
tabs.forEachIndexed { index, title ->
BottomNavigationItem(
icon = { Icon(painter = icons[index], contentDescription = title) },
label = { Text(title) },
selected = selectedTab == index,
onClick = { selectedTab = index },
alwaysShowLabel = true,
selectedContentColor = Color.White,
unselectedContentColor = Color.White.copy(alpha = 0.7f),
)
}
}
}
) {
when (selectedTab) {
0 -> HomeView()
1 -> MediaView()
2 -> VideosView()
3 -> ContactView()
}
}
И мой theme.xml
<?xml version = "1.0" encoding = "utf-8"?>
<resources xmlns:tools = "http://schemas.android.com/tools">
<style name = "Theme.HSMApp" parent = "android:Theme.Material.Light.NoActionBar" >
<item name = "colorPrimary">@color/primaryColor</item>
<item name = "colorPrimaryVariant">@color/primaryVariantColor</item>
<!-- Secondary brand color. -->
<item name = "colorSecondary">@color/secondaryColor</item>
<!-- Status bar color. -->
<item name = "android:statusBarColor" tools:targetApi = "l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
У меня тоже это есть в Theme.kt
package com.phela.hsmapp.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun HSMAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
Что мне следует изменить?
Как уже упоминалось в комментариях, это вызвано смешиванием компонентов Compose Материала 2 и Материала 3. Однако я настоятельно советую не использовать ответ на связанный вопрос: он понижает уровень ваших компонентов Материала 3 до Материала 2. Поскольку вы также используете других компонентов Материала 3 это неизбежно приведет к дальнейшим осложнениям.
Вместо этого удалите все компоненты Material 2 в своем приложении и полностью полагайтесь на Material 3. Просмотрите файлы Gradle (или каталог версий, если вы его используете) на предмет любых зависимостей, которые начинаются с androidx.compose.material:
. Они предоставляют старые компоненты Material 2. Удалите их и найдите альтернативы, начинающиеся с androidx.compose.material3:
.
В вашем примере BottomNavigation
и BottomNavigationItem
являются частью androidx.compose.material:material
. Замените эту зависимость эквивалентом Материала 3 androidx.compose.material3:material3
. Компоненты Compose во многом схожи, но большинство из них различаются в определенных аспектах. В вашем случае это означает, что BottomNavigation
становится NavigationBar
, а BottomNavigationItem
становится NavigationBarItem
. Также изменились параметры цвета. С новыми компонентами Material 3 это будет выглядеть так:
NavigationBar(
containerColor = Color(0xff6c247c),
contentColor = Color.White,
) {
tabs.forEachIndexed { index, title ->
NavigationBarItem(
icon = { Icon(painter = icons[index], contentDescription = title) },
label = { Text(title) },
selected = selectedTab == index,
onClick = { selectedTab = index },
alwaysShowLabel = true,
colors = NavigationBarItemDefaults.colors().copy(
selectedIconColor = Color.White,
selectedTextColor = Color.White,
unselectedIconColor = Color.White.copy(alpha = 0.7f),
unselectedTextColor = Color.White.copy(alpha = 0.7f),
),
)
}
}
Тем не менее, в Материале 3 вам следует использовать тему, определенную в вашем Theme.kt
. Таким образом, вам не придется вручную определять цвета для каждого компонента, вместо этого компоненты получают нужные им цвета из цветовой схемы, определенной в теме. Это также автоматически позаботится об изменении цветов при переключении в темный режим.
На данный момент у вас определены только primary
, secondary
и tertiary
. Другие варианты цвета являются производными от этих цветов. Однако вы также можете указать их явно:
surfaceContainer
для NavigationBar
containerColor
onSecondaryContainer
для NavigationBarItem
selectedIconColor
onSurface
для NavigationBarItem
selectedTextColor
onSurfaceVariant
для NavigationBarItem
unselectedIconColor
и unselectedTextColor
(Символ NavigationBar
contentColor
нигде не используется, поэтому я его опустил.)
Ваш LightColorScheme
можно определить так:
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40,
surfaceContainer = Color(0xff6c247c),
onSecondaryContainer = Color.White,
onSurface = Color.White,
onSurfaceVariant = Color.White.copy(alpha = 0.7f),
)
Вы также должны определить соответствующие цвета для DarkColorScheme
, которые будут использоваться, когда пользователь переключается в темный режим.
Теперь вы можете удалить все цвета с панели навигации следующим образом:
NavigationBar {
tabs.forEachIndexed { index, title ->
NavigationBarItem(
icon = { Icon(painter = icons[index], contentDescription = title) },
label = { Text(title) },
selected = selectedTab == index,
onClick = { selectedTab = index },
alwaysShowLabel = true,
)
}
}
Теперь имейте в виду, что все цвета, определенные в теме, также влияют на другие составные элементы, а не только на панель навигации. Это сделано специально, поэтому общий вид приложения одинаков для всех компонентов. Возможно, вы захотите изменить значения, чтобы улучшить его. Если вы не хотите определять все значения цвета вручную, вы можете использовать Конструктор тем материалов. Это веб-сайт, который вы можете использовать для автоматического создания и загрузки файла Theme.kt
с соответствующими цветами для некоторых заданных вами настроек.
Сказав все это, вы, возможно, захотите заменить весь каркас на NavigationSuiteScaffold
. Он основан на NavigationBar
и NavigationBarItem
, поэтому внутри него используются те же компоненты и та же тема, но он также поддерживает другие виды навигационных компонентов, например NavigationRail
(размещается сбоку) или NavigationDrawer
(маленькая полоска сбоку). , можно оформить). Какой из них будет использоваться, затем решается во время выполнения в зависимости от доступного размера экрана, как рекомендовано в Навигация в Материале 3.
Имейте в виду, что это все еще экспериментальный вариант, поэтому API может измениться в будущем. На данный момент вы можете заменить весь Scaffold следующим образом:
NavigationSuiteScaffold(
navigationSuiteItems = {
tabs.forEachIndexed { index, title ->
item(
icon = { Icon(painter = icons[index], contentDescription = title) },
label = { Text(title) },
selected = selectedTab == index,
onClick = { selectedTab = index },
alwaysShowLabel = true,
)
}
},
) {
Column {
when (selectedTab) {
0 -> HomeView()
1 -> MediaView()
2 -> VideosView()
3 -> ContactView()
}
}
}
Вам нужно добавить зависимость Gradle androidx.compose.material3:material3-adaptive-navigation-suite-android.
Большое спасибо за подробную информацию. Так все получилось. 🙏🏻🙂
Отвечает ли это на ваш вопрос?