feat: Improve UI and theme handling
This commit introduces several UI and theming enhancements:
- Adds labels to the "Dark theme" and "Dynamic theme" switches for better clarity.
- Implements dynamic status bar icon colors to match the current theme (light/dark), improving system integration.
- Enhances the color grid items by:
- Automatically calculating and applying a contrasting content color (text and border) for better readability against the background color.
- Displaying the hex code of the color.
- Bumps the Compose BOM version to `2025.12.00`.
This commit is contained in:
@@ -42,11 +42,13 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import dev.meloda.app.materialcolors.ui.theme.AppTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
@@ -66,7 +68,7 @@ fun RootContent() {
|
||||
|
||||
AppTheme(
|
||||
darkTheme = dark,
|
||||
dynamicColor = dynamic
|
||||
dynamicColor = dynamic,
|
||||
) {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { padding ->
|
||||
Column(
|
||||
@@ -78,14 +80,21 @@ fun RootContent() {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
Switch(
|
||||
checked = dark,
|
||||
onCheckedChange = { dark = it },
|
||||
)
|
||||
Switch(
|
||||
checked = dynamic,
|
||||
onCheckedChange = { dynamic = it },
|
||||
)
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text = "Dark theme")
|
||||
Switch(
|
||||
checked = dark,
|
||||
onCheckedChange = { dark = it },
|
||||
)
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text = "Dynamic theme")
|
||||
Switch(
|
||||
checked = dynamic,
|
||||
onCheckedChange = { dynamic = it },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ColorsGrid()
|
||||
@@ -187,9 +196,9 @@ fun ColorsGrid(
|
||||
|
||||
@Composable
|
||||
private fun ColorGridItem(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
color: ULong
|
||||
color: ULong,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val animatedColor by animateColorAsState(
|
||||
@@ -197,7 +206,34 @@ private fun ColorGridItem(
|
||||
label = "animate color"
|
||||
)
|
||||
|
||||
val shape = RoundedCornerShape(25)
|
||||
val shape = remember {
|
||||
RoundedCornerShape(25)
|
||||
}
|
||||
|
||||
val color = remember(color) {
|
||||
Color(color)
|
||||
}
|
||||
val isLight = remember(color) {
|
||||
ColorUtils.calculateLuminance(color.toArgb()) >= 0.5f
|
||||
}
|
||||
val hex = remember(color) {
|
||||
"#%02X%02X%02X".format(
|
||||
(color.red * 255).toInt(),
|
||||
(color.green * 255).toInt(),
|
||||
(color.blue * 255).toInt()
|
||||
)
|
||||
}
|
||||
|
||||
val borderColor by animateColorAsState(
|
||||
targetValue = if (isLight) Color.DarkGray else Color.LightGray,
|
||||
label = "borderColor"
|
||||
)
|
||||
|
||||
val contentColor by animateColorAsState(
|
||||
targetValue = MaterialTheme.colorScheme.contentColorFor(Color(color.value))
|
||||
.takeIf { it != Color.Unspecified } ?: if (isLight) Color.Black else Color.White,
|
||||
label = "contentColor"
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
@@ -205,16 +241,10 @@ private fun ColorGridItem(
|
||||
.background(color = animatedColor)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = Color(0xffCCCCCC),
|
||||
color = borderColor,
|
||||
shape = shape
|
||||
)
|
||||
.clickable {
|
||||
val color = Color(color)
|
||||
val hex = "#%02X%02X%02X".format(
|
||||
(color.red * 255).toInt(),
|
||||
(color.green * 255).toInt(),
|
||||
(color.blue * 255).toInt()
|
||||
)
|
||||
Log.d("Material Colors", "picked color: $hex")
|
||||
|
||||
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager)
|
||||
@@ -233,7 +263,7 @@ private fun ColorGridItem(
|
||||
Text(
|
||||
text = title,
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colorScheme.contentColorFor(Color(color)),
|
||||
color = contentColor,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
fontSize = 12.sp,
|
||||
letterSpacing = 0.sp,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.meloda.app.materialcolors.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -8,7 +9,10 @@ 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.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
@Composable
|
||||
fun AppTheme(
|
||||
@@ -26,6 +30,15 @@ fun AppTheme(
|
||||
else -> lightColorScheme()
|
||||
}
|
||||
|
||||
val view = LocalView.current
|
||||
if (!view.isInEditMode) {
|
||||
SideEffect {
|
||||
val window = (view.context as Activity).window
|
||||
val insetsController = WindowCompat.getInsetsController(window, view)
|
||||
insetsController.isAppearanceLightStatusBars = !darkTheme
|
||||
}
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
|
||||
@@ -4,7 +4,7 @@ kotlin = "2.2.0"
|
||||
coreKtx = "1.16.0"
|
||||
lifecycleRuntimeKtx = "2.9.1"
|
||||
activityCompose = "1.10.1"
|
||||
composeBom = "2025.06.01"
|
||||
composeBom = "2025.12.00"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
|
||||
Reference in New Issue
Block a user