更新
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import taskttl.composeapp.generated.resources.Res
|
||||
import taskttl.composeapp.generated.resources.action
|
||||
import taskttl.composeapp.generated.resources.back
|
||||
|
||||
/**
|
||||
* 应用程序标题
|
||||
* @param [title] 标题
|
||||
* @param [showBack] 显示返回
|
||||
* @param [onBackClick] 上返回点击
|
||||
* @param [trailingIcon] 尾随图标
|
||||
* @param [onTrailingClick] 尾随点击
|
||||
*/
|
||||
@Composable
|
||||
fun AppHeader(
|
||||
title: StringResource,
|
||||
showBack: Boolean = false,
|
||||
onBackClick: (() -> Unit)? = null,
|
||||
trailingIcon: ImageVector? = null,
|
||||
onTrailingClick: (() -> Unit)? = null
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
Brush.linearGradient(
|
||||
colors = listOf(Color(0xFF667EEA), Color(0xFF764BA2))
|
||||
)
|
||||
)
|
||||
.padding(horizontal = 20.dp, vertical = 15.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (showBack && onBackClick != null) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = stringResource(Res.string.back),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.clickable { onBackClick() }
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = stringResource(title),
|
||||
color = Color.White,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
|
||||
if (trailingIcon != null) {
|
||||
Icon(
|
||||
imageVector = trailingIcon,
|
||||
contentDescription = stringResource(Res.string.action),
|
||||
tint = Color.White,
|
||||
modifier = Modifier.clickable { onTrailingClick?.invoke() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.taskttl.data.local.model.Category
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CategoryCard(
|
||||
category: Category,
|
||||
isSelected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onClick.invoke() },
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = if (isSelected) {
|
||||
category.color.backgroundColor.copy(alpha = 0.1f)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface
|
||||
}
|
||||
),
|
||||
border = if (isSelected) BorderStroke(2.dp, category.color.backgroundColor) else null
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(4.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(30.dp)
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.background(category.color.backgroundColor.copy(alpha = 0.2f)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = category.icon.icon,
|
||||
contentDescription = stringResource(category.icon.displayNameRes),
|
||||
tint = category.color.iconColor,
|
||||
modifier = Modifier.size(25.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
Text(
|
||||
text = category.name,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = if (isSelected) category.color.textColor else MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.FilterChipDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.taskttl.data.local.model.Category
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import taskttl.composeapp.generated.resources.Res
|
||||
import taskttl.composeapp.generated.resources.all_text
|
||||
|
||||
@Composable
|
||||
fun CategoryFilter(
|
||||
categories: List<Category>,
|
||||
selectedCategory: Category?,
|
||||
onCategorySelected: (Category?) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
LazyRow(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// 全部分类
|
||||
item {
|
||||
FilterChip(
|
||||
selected = selectedCategory == null,
|
||||
onClick = { onCategorySelected(null) },
|
||||
label = { Text(stringResource(Res.string.all_text)) }
|
||||
)
|
||||
}
|
||||
|
||||
// 各个分类
|
||||
items(categories) { category ->
|
||||
FilterChip(
|
||||
selected = selectedCategory == category,
|
||||
onClick = { onCategorySelected(category) },
|
||||
label = { Text(category.name, color = category.color.textColor) },
|
||||
colors = FilterChipDefaults.filterChipColors(
|
||||
selectedContainerColor = category.color.backgroundColor,
|
||||
selectedLabelColor = category.color.backgroundColor
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.taskttl.data.local.model.CategoryStatistics
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import taskttl.composeapp.generated.resources.Res
|
||||
import taskttl.composeapp.generated.resources.active
|
||||
import taskttl.composeapp.generated.resources.completed
|
||||
import taskttl.composeapp.generated.resources.completion_rate
|
||||
import taskttl.composeapp.generated.resources.total_countdowns
|
||||
import taskttl.composeapp.generated.resources.total_tasks
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CategoryStatisticsCard(
|
||||
statistics: CategoryStatistics,
|
||||
categoryColor: Long,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.clip(CircleShape)
|
||||
.background(Color(categoryColor))
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
Text(
|
||||
text = statistics.categoryName,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// 任务统计
|
||||
if (statistics.totalTasks > 0) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(Res.string.total_tasks),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = "${statistics.totalTasks}",
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(Res.string.completed),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = "${statistics.completedTasks}",
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(Res.string.completion_rate),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = "${(statistics.completionRate * 100).toInt()}%",
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = if (statistics.completionRate >= 0.8f)
|
||||
MaterialTheme.colorScheme.primary
|
||||
else MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
// 进度条
|
||||
LinearProgressIndicator(
|
||||
progress = { statistics.completionRate },
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(8.dp)
|
||||
.clip(RoundedCornerShape(4.dp)),
|
||||
color = Color(categoryColor),
|
||||
trackColor = ProgressIndicatorDefaults.linearTrackColor,
|
||||
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
|
||||
)
|
||||
}
|
||||
|
||||
// 倒数日统计
|
||||
if (statistics.totalCountdowns > 0) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(Res.string.total_countdowns),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = "${statistics.totalCountdowns}",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
}
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(Res.string.active),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = "${statistics.activeCountdowns}",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.DatePickerDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.rememberDatePickerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toInstant
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import taskttl.composeapp.generated.resources.Res
|
||||
import taskttl.composeapp.generated.resources.cancel
|
||||
import taskttl.composeapp.generated.resources.confirm
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.Instant
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalTime::class)
|
||||
@Composable
|
||||
fun CompactDatePickerDialog(
|
||||
show: Boolean,
|
||||
initialSelected: LocalDateTime?,
|
||||
onConfirm: (LocalDateTime) -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
if (!show) return
|
||||
|
||||
val initialMillis = (
|
||||
initialSelected?.toInstant(TimeZone.currentSystemDefault())
|
||||
?: Clock.System.now()
|
||||
).toEpochMilliseconds()
|
||||
|
||||
val state = rememberDatePickerState(initialSelectedDateMillis = initialMillis)
|
||||
|
||||
DatePickerDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
val millis = state.selectedDateMillis
|
||||
if (millis != null) {
|
||||
val instant = Instant.fromEpochMilliseconds(millis)
|
||||
val selected = instant.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
onConfirm(selected)
|
||||
}
|
||||
onDismiss()
|
||||
}
|
||||
) { Text(stringResource(Res.string.confirm)) }
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) { Text(stringResource(Res.string.cancel)) }
|
||||
}
|
||||
) {
|
||||
DatePicker(
|
||||
state = state,
|
||||
headline = null,
|
||||
title = null,
|
||||
showModeToggle = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.taskttl.ui.components
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Clear
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import taskttl.composeapp.generated.resources.Res
|
||||
import taskttl.composeapp.generated.resources.clear_text
|
||||
import taskttl.composeapp.generated.resources.search
|
||||
import taskttl.composeapp.generated.resources.search_placeholder
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SearchBar(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: StringResource = Res.string.search_placeholder
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = query,
|
||||
onValueChange = onQueryChange,
|
||||
modifier = modifier,
|
||||
placeholder = { Text(stringResource(placeholder)) },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = stringResource(Res.string.search)
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (query.isNotEmpty()) {
|
||||
IconButton(onClick = { onQueryChange("") }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Clear,
|
||||
contentDescription = stringResource(Res.string.clear_text)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
singleLine = true
|
||||
)
|
||||
}
|
||||
109
composeApp/src/commonMain/kotlin/com/taskttl/ui/theme/Theme.kt
Normal file
109
composeApp/src/commonMain/kotlin/com/taskttl/ui/theme/Theme.kt
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.taskttl.ui.theme
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/** 浅色方案 */
|
||||
private val LightColorScheme = lightColorScheme(
|
||||
primary = Color(0xFF6750A4),
|
||||
onPrimary = Color(0xFFFFFFFF),
|
||||
primaryContainer = Color(0xFFEADDFF),
|
||||
onPrimaryContainer = Color(0xFF21005D),
|
||||
secondary = Color(0xFF625B71),
|
||||
onSecondary = Color(0xFFFFFFFF),
|
||||
secondaryContainer = Color(0xFFE8DEF8),
|
||||
onSecondaryContainer = Color(0xFF1D192B),
|
||||
tertiary = Color(0xFF7D5260),
|
||||
onTertiary = Color(0xFFFFFFFF),
|
||||
tertiaryContainer = Color(0xFFFFD8E4),
|
||||
onTertiaryContainer = Color(0xFF31111D),
|
||||
error = Color(0xFFBA1A1A),
|
||||
onError = Color(0xFFFFFFFF),
|
||||
errorContainer = Color(0xFFFFDAD6),
|
||||
onErrorContainer = Color(0xFF410002),
|
||||
background = Color(0xFFFFFBFE),
|
||||
onBackground = Color(0xFF1C1B1F),
|
||||
surface = Color(0xFFFFFBFE),
|
||||
onSurface = Color(0xFF1C1B1F),
|
||||
surfaceVariant = Color(0xFFE7E0EC),
|
||||
onSurfaceVariant = Color(0xFF49454F),
|
||||
outline = Color(0xFF79747E),
|
||||
outlineVariant = Color(0xFFCAC4D0),
|
||||
scrim = Color(0xFF000000),
|
||||
inverseSurface = Color(0xFF313033),
|
||||
inverseOnSurface = Color(0xFFF4EFF4),
|
||||
inversePrimary = Color(0xFFD0BCFF),
|
||||
surfaceDim = Color(0xFFDDD8DD),
|
||||
surfaceBright = Color(0xFFFFFBFE),
|
||||
surfaceContainerLowest = Color(0xFFFFFFFF),
|
||||
surfaceContainerLow = Color(0xFFF7F2FA),
|
||||
surfaceContainer = Color(0xFFF1ECF4),
|
||||
surfaceContainerHigh = Color(0xFFECE6F0),
|
||||
surfaceContainerHighest = Color(0xFFE6E0E9)
|
||||
)
|
||||
|
||||
/** 深色配色方案 */
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
primary = Color(0xFFD0BCFF),
|
||||
onPrimary = Color(0xFF381E72),
|
||||
primaryContainer = Color(0xFF4F378B),
|
||||
onPrimaryContainer = Color(0xFFEADDFF),
|
||||
secondary = Color(0xFFCCC2DC),
|
||||
onSecondary = Color(0xFF332D41),
|
||||
secondaryContainer = Color(0xFF4A4458),
|
||||
onSecondaryContainer = Color(0xFFE8DEF8),
|
||||
tertiary = Color(0xFFEFB8C8),
|
||||
onTertiary = Color(0xFF492532),
|
||||
tertiaryContainer = Color(0xFF633B48),
|
||||
onTertiaryContainer = Color(0xFFFFD8E4),
|
||||
error = Color(0xFFFFB4AB),
|
||||
onError = Color(0xFF690005),
|
||||
errorContainer = Color(0xFF93000A),
|
||||
onErrorContainer = Color(0xFFFFDAD6),
|
||||
background = Color(0xFF10131C),
|
||||
onBackground = Color(0xFFE6E0E9),
|
||||
surface = Color(0xFF10131C),
|
||||
onSurface = Color(0xFFE6E0E9),
|
||||
surfaceVariant = Color(0xFF49454F),
|
||||
onSurfaceVariant = Color(0xFFCAC4D0),
|
||||
outline = Color(0xFF938F99),
|
||||
outlineVariant = Color(0xFF49454F),
|
||||
scrim = Color(0xFF000000),
|
||||
inverseSurface = Color(0xFFE6E0E9),
|
||||
inverseOnSurface = Color(0xFF313033),
|
||||
inversePrimary = Color(0xFF6750A4),
|
||||
surfaceDim = Color(0xFF10131C),
|
||||
surfaceBright = Color(0xFF383B42),
|
||||
surfaceContainerLowest = Color(0xFF0B0E17),
|
||||
surfaceContainerLow = Color(0xFF191C24),
|
||||
surfaceContainer = Color(0xFF1D2028),
|
||||
surfaceContainerHigh = Color(0xFF282A32),
|
||||
surfaceContainerHighest = Color(0xFF33353D)
|
||||
)
|
||||
|
||||
/**
|
||||
* 应用主题
|
||||
* @param [darkTheme] 黑暗主题
|
||||
* @param [content] 内容
|
||||
*/
|
||||
@Composable
|
||||
fun AppTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colorScheme = if (darkTheme) {
|
||||
DarkColorScheme
|
||||
} else {
|
||||
LightColorScheme
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = mainTypography(),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.taskttl.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
|
||||
/**
|
||||
* 主要排版
|
||||
* @return [Typography]
|
||||
*/
|
||||
@Composable
|
||||
fun mainTypography(): Typography {
|
||||
return Typography(
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
),
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 11.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user