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.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.core.graphics.ColorUtils
|
||||||
import dev.meloda.app.materialcolors.ui.theme.AppTheme
|
import dev.meloda.app.materialcolors.ui.theme.AppTheme
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@@ -66,7 +68,7 @@ fun RootContent() {
|
|||||||
|
|
||||||
AppTheme(
|
AppTheme(
|
||||||
darkTheme = dark,
|
darkTheme = dark,
|
||||||
dynamicColor = dynamic
|
dynamicColor = dynamic,
|
||||||
) {
|
) {
|
||||||
Scaffold(modifier = Modifier.fillMaxSize()) { padding ->
|
Scaffold(modifier = Modifier.fillMaxSize()) { padding ->
|
||||||
Column(
|
Column(
|
||||||
@@ -78,15 +80,22 @@ fun RootContent() {
|
|||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
) {
|
) {
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
Text(text = "Dark theme")
|
||||||
Switch(
|
Switch(
|
||||||
checked = dark,
|
checked = dark,
|
||||||
onCheckedChange = { dark = it },
|
onCheckedChange = { dark = it },
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
|
Text(text = "Dynamic theme")
|
||||||
Switch(
|
Switch(
|
||||||
checked = dynamic,
|
checked = dynamic,
|
||||||
onCheckedChange = { dynamic = it },
|
onCheckedChange = { dynamic = it },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ColorsGrid()
|
ColorsGrid()
|
||||||
}
|
}
|
||||||
@@ -187,9 +196,9 @@ fun ColorsGrid(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColorGridItem(
|
private fun ColorGridItem(
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
title: String,
|
title: String,
|
||||||
color: ULong
|
color: ULong,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val animatedColor by animateColorAsState(
|
val animatedColor by animateColorAsState(
|
||||||
@@ -197,7 +206,34 @@ private fun ColorGridItem(
|
|||||||
label = "animate color"
|
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(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@@ -205,16 +241,10 @@ private fun ColorGridItem(
|
|||||||
.background(color = animatedColor)
|
.background(color = animatedColor)
|
||||||
.border(
|
.border(
|
||||||
width = 1.dp,
|
width = 1.dp,
|
||||||
color = Color(0xffCCCCCC),
|
color = borderColor,
|
||||||
shape = shape
|
shape = shape
|
||||||
)
|
)
|
||||||
.clickable {
|
.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")
|
Log.d("Material Colors", "picked color: $hex")
|
||||||
|
|
||||||
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager)
|
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager)
|
||||||
@@ -233,7 +263,7 @@ private fun ColorGridItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
color = MaterialTheme.colorScheme.contentColorFor(Color(color)),
|
color = contentColor,
|
||||||
style = MaterialTheme.typography.labelSmall,
|
style = MaterialTheme.typography.labelSmall,
|
||||||
fontSize = 12.sp,
|
fontSize = 12.sp,
|
||||||
letterSpacing = 0.sp,
|
letterSpacing = 0.sp,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.meloda.app.materialcolors.ui.theme
|
package dev.meloda.app.materialcolors.ui.theme
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -8,7 +9,10 @@ import androidx.compose.material3.dynamicDarkColorScheme
|
|||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppTheme(
|
fun AppTheme(
|
||||||
@@ -26,6 +30,15 @@ fun AppTheme(
|
|||||||
else -> lightColorScheme()
|
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(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
typography = Typography,
|
typography = Typography,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ kotlin = "2.2.0"
|
|||||||
coreKtx = "1.16.0"
|
coreKtx = "1.16.0"
|
||||||
lifecycleRuntimeKtx = "2.9.1"
|
lifecycleRuntimeKtx = "2.9.1"
|
||||||
activityCompose = "1.10.1"
|
activityCompose = "1.10.1"
|
||||||
composeBom = "2025.06.01"
|
composeBom = "2025.12.00"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
|||||||
Reference in New Issue
Block a user