Colors, style adjustments

This commit is contained in:
Pierre-Yves Nicolas
2025-07-03 08:59:58 +02:00
parent ca2972f0df
commit 7321e271b8
6 changed files with 153 additions and 62 deletions

View File

@@ -16,10 +16,50 @@ package org.mydomain.myscan.ui.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF) val Primary = Color(0xFF33BE41)
val PurpleGrey80 = Color(0xFFCCC2DC) val OnPrimary = Color(0xFFFFFFFF)
val Pink80 = Color(0xFFEFB8C8) val PrimaryContainer = Color(0xFF7BD785)
val OnPrimaryContainer = Color(0xFF0D3311)
val Secondary = Color(0xFF52CBA7)
val OnSecondary = Color(0xFFFFFFFF)
val SecondaryContainer = Color(0xFFBAE6D8)
val OnSecondaryContainer = Color(0xFF14332A)
val Tertiary = Color(0xFF8976D6)
val OnTertiary = Color(0xFFFFFFFF)
val TertiaryContainer = Color(0xFFCBC5E6)
val OnTertiaryContainer = Color(0xFF211C33)
val Error = Color(0xFFB3261E)
val OnError = Color(0xFFFFFFFF)
val ErrorContainer = Color(0xFFE6ACA9)
val OnErrorContainer = Color(0xFF330B09)
val Background = Color(0xFFfcfcfc)
val OnBackground = Color(0xFF313331)
val Surface = Color(0xFFfcfcfc)
val OnSurface = Color(0xFF313331)
val SurfaceVariant = Color(0xFFdbe6dc)
val OnSurfaceVariant = Color(0xFF576658)
val Outline = Color(0xFF829984)
val Purple40 = Color(0xFF6650a4) val PrimaryDark = Color(0xFF9AE6A1)
val PurpleGrey40 = Color(0xFF625b71) val OnPrimaryDark = Color(0xFF144C19)
val Pink40 = Color(0xFF7D5260) val PrimaryContainerDark = Color(0xFF1B6622)
val OnPrimaryContainerDark = Color(0xFFB0E6B5)
val SecondaryDark = Color(0xFFA8E6D3)
val OnSecondaryDark = Color(0xFF1F4C3F)
val SecondaryContainerDark = Color(0xFF296654)
val OnSecondaryContainerDark = Color(0xFFBAE6D8)
val TertiaryDark = Color(0xFFC1B7E6)
val OnTertiaryDark = Color(0xFF312A4C)
val TertiaryContainerDark = Color(0xFF413866)
val OnTertiaryContainerDark = Color(0xFFCBC5E6)
val ErrorDark = Color(0xFFE69490)
val OnErrorDark = Color(0xFF4C100D)
val ErrorContainerDark = Color(0xFF661511)
val OnErrorContainerDark = Color(0xFFE6ACA9)
val BackgroundDark = Color(0xFF313331)
val OnBackgroundDark = Color(0xFFe3e6e3)
val SurfaceDark = Color(0xFF313331)
val OnSurfaceDark = Color(0xFFe3e6e3)
val SurfaceVariantDark = Color(0xFF576658)
val OnSurfaceVariantDark = Color(0xFFd6e6d8)
val OutlineDark = Color(0xFFa2b3a3)

View File

@@ -14,52 +14,70 @@
*/ */
package org.mydomain.myscan.ui.theme package org.mydomain.myscan.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
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.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme( private val DarkColorScheme = darkColorScheme(
primary = Purple80, primary = PrimaryDark,
secondary = PurpleGrey80, onPrimary = OnPrimaryDark,
tertiary = Pink80 primaryContainer = PrimaryContainerDark,
onPrimaryContainer = OnPrimaryContainerDark,
secondary = SecondaryDark,
onSecondary = OnSecondaryDark,
secondaryContainer = SecondaryContainerDark,
onSecondaryContainer = OnSecondaryContainerDark,
tertiary = TertiaryDark,
onTertiary = OnTertiaryDark,
tertiaryContainer = TertiaryContainerDark,
onTertiaryContainer = OnTertiaryContainerDark,
error = ErrorDark,
onError = OnErrorDark,
errorContainer = ErrorContainerDark,
onErrorContainer = OnErrorContainerDark,
background = BackgroundDark,
onBackground = OnBackgroundDark,
surface = SurfaceDark,
onSurface = OnSurfaceDark,
surfaceVariant = SurfaceVariantDark,
onSurfaceVariant = OnSurfaceVariantDark,
outline = OutlineDark
) )
private val LightColorScheme = lightColorScheme( private val LightColorScheme = lightColorScheme(
primary = Purple40, primary = Primary,
secondary = PurpleGrey40, onPrimary = OnPrimary,
tertiary = Pink40 primaryContainer = PrimaryContainer,
onPrimaryContainer = OnPrimaryContainer,
/* Other default colors to override secondary = Secondary,
background = Color(0xFFFFFBFE), onSecondary = OnSecondary,
surface = Color(0xFFFFFBFE), secondaryContainer = SecondaryContainer,
onPrimary = Color.White, onSecondaryContainer = OnSecondaryContainer,
onSecondary = Color.White, tertiary = Tertiary,
onTertiary = Color.White, onTertiary = OnTertiary,
onBackground = Color(0xFF1C1B1F), tertiaryContainer = TertiaryContainer,
onSurface = Color(0xFF1C1B1F), onTertiaryContainer = OnTertiaryContainer,
*/ error = Error,
onError = OnError,
errorContainer = ErrorContainer,
onErrorContainer = OnErrorContainer,
background = Background,
onBackground = OnBackground,
surface = Surface,
onSurface = OnSurface,
surfaceVariant = SurfaceVariant,
onSurfaceVariant = OnSurfaceVariant,
outline = Outline
) )
@Composable @Composable
fun MyScanTheme( fun MyScanTheme(
darkTheme: Boolean = isSystemInDarkTheme(), darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
val colorScheme = when { 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 darkTheme -> DarkColorScheme
else -> LightColorScheme else -> LightColorScheme
} }

View File

@@ -34,6 +34,7 @@ import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView import androidx.camera.view.PreviewView
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@@ -155,6 +156,7 @@ fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState, debugMode: Boolean) {
if (binaryMask == null) { if (binaryMask == null) {
return return
} }
val quadColor = MaterialTheme.colorScheme.primary
Canvas(modifier = Modifier.fillMaxSize()) { Canvas(modifier = Modifier.fillMaxSize()) {
if (debugMode) { if (debugMode) {
drawMask(this, binaryMask) drawMask(this, binaryMask)
@@ -167,7 +169,7 @@ fun AnalysisOverlay(liveAnalysisState: LiveAnalysisState, debugMode: Boolean) {
toHeight = size.height.toInt() toHeight = size.height.toInt()
) )
scaledQuad.edges().forEach { scaledQuad.edges().forEach {
drawLine(Color.Green, it.from.toOffset(), it.to.toOffset(), 10.0f) drawLine(quadColor, it.from.toOffset(), it.to.toOffset(), 10.0f)
} }
} }
} }

View File

@@ -391,7 +391,7 @@ fun CameraScreenFooter(
Column (modifier = Modifier.background(MaterialTheme.colorScheme.surfaceContainer)) { Column (modifier = Modifier.background(MaterialTheme.colorScheme.surfaceContainer)) {
pageList() pageList()
BottomAppBar( BottomAppBar(
containerColor = Color.Transparent containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
) { ) {
Row ( Row (
modifier = Modifier modifier = Modifier

View File

@@ -37,12 +37,12 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.BottomAppBar import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallFloatingActionButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
@@ -58,6 +58,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
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
@@ -91,8 +92,8 @@ fun DocumentScreen(
topBar = { topBar = {
TopAppBar( TopAppBar(
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer, containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
titleContentColor = MaterialTheme.colorScheme.primary, titleContentColor = MaterialTheme.colorScheme.onSurface,
), ),
title = { Text("Finalize document") }, title = { Text("Finalize document") },
navigationIcon = { navigationIcon = {
@@ -106,6 +107,7 @@ fun DocumentScreen(
Column { Column {
PageList(pageIds, imageLoader, currentPageIndex, toCameraScreen) PageList(pageIds, imageLoader, currentPageIndex, toCameraScreen)
BottomAppBar( BottomAppBar(
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
actions = { actions = {
Button(onClick = onSharePressed) { Button(onClick = onSharePressed) {
Icon(Icons.Default.Share, contentDescription = "Share") Icon(Icons.Default.Share, contentDescription = "Share")
@@ -120,9 +122,12 @@ fun DocumentScreen(
} }
}, },
floatingActionButton = { floatingActionButton = {
FloatingActionButton(onClick = { showDialog.value = true }) { MyIconButton(
Icon(Icons.Default.RestartAlt, contentDescription = "Close") icon = Icons.Default.RestartAlt,
} contentDescription = "Restart",
onClick = { showDialog.value = true },
modifier = Modifier.padding(vertical = 8.dp)
)
} }
) )
} }
@@ -147,7 +152,7 @@ private fun DocumentPreview(
Column ( Column (
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceContainer) .background(MaterialTheme.colorScheme.surfaceContainerLow)
.padding(padding) .padding(padding)
) { ) {
Box ( Box (
@@ -163,6 +168,7 @@ private fun DocumentPreview(
LaunchedEffect(imageId) { LaunchedEffect(imageId) {
zoomState.reset() zoomState.reset()
} }
Box(modifier = Modifier.fillMaxSize(0.92f).align(Alignment.Center)) {
Image( Image(
bitmap = imageBitmap, bitmap = imageBitmap,
contentDescription = null, contentDescription = null,
@@ -172,14 +178,15 @@ private fun DocumentPreview(
.zoomable(zoomState) .zoomable(zoomState)
) )
} }
SmallFloatingActionButton( }
MyIconButton(
Icons.Outlined.Delete,
contentDescription = "Delete page",
onClick = { onDeleteImage(imageId) }, onClick = { onDeleteImage(imageId) },
modifier = Modifier modifier = Modifier
.align(Alignment.TopEnd) .align(Alignment.TopEnd)
.padding(4.dp) .padding(8.dp)
) { )
Icon(imageVector = Icons.Outlined.Delete, contentDescription = "Delete page")
}
Text("${currentPageIndex.intValue + 1} / ${pageIds.size}", Text("${currentPageIndex.intValue + 1} / ${pageIds.size}",
color = MaterialTheme.colorScheme.inverseOnSurface, color = MaterialTheme.colorScheme.inverseOnSurface,
modifier = Modifier modifier = Modifier
@@ -206,14 +213,14 @@ private fun PageList(
onPageClick = { index -> currentPageIndex.value = index }, onPageClick = { index -> currentPageIndex.value = index },
currentPageIndex = currentPageIndex.value, currentPageIndex = currentPageIndex.value,
) )
SmallFloatingActionButton( MyIconButton(
icon = Icons.Default.Add,
onClick = toCameraScreen, onClick = toCameraScreen,
contentDescription = "Add page",
modifier = Modifier modifier = Modifier
.align(Alignment.CenterEnd) .align(Alignment.CenterEnd)
.padding(8.dp) .padding(8.dp)
) { )
Icon(imageVector = Icons.Default.Add, contentDescription = "Add page")
}
} }
} }
@@ -239,6 +246,30 @@ fun NewDocumentDialog(onConfirm: () -> Unit, showDialog: MutableState<Boolean>)
) )
} }
@Composable
fun MyIconButton(
icon: ImageVector,
contentDescription: String,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
FilledIconButton (
onClick = onClick,
colors = IconButtonDefaults.outlinedIconButtonColors(
containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.6f),
contentColor = MaterialTheme.colorScheme.primary
),
modifier = modifier.size(40.dp)
) {
Icon(
imageVector = icon,
contentDescription = contentDescription,
tint = MaterialTheme.colorScheme.primary
)
}
}
@Composable @Composable
@Preview @Preview
fun DocumentScreenPreview() { fun DocumentScreenPreview() {

View File

@@ -60,7 +60,7 @@ fun CommonPageList(
LazyRow ( LazyRow (
state = listState, state = listState,
contentPadding = PaddingValues(4.dp), contentPadding = PaddingValues(4.dp),
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.surfaceContainer),
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {