Я хочу предоставить параметр функции @Composable, которая принимает цвет, но только один из дискретного списка.
Что-то в этом роде:
enum class SpecialColor(val color: Color) {
ALPHA(MaterialTheme.colors.onSurface),
BETA(MaterialTheme.colors.onSecondary)
}
@Composable
fun ColorSample(specialColor: SpecialColor) {
Box(
modifier = Modifier
.width(100.dp)
.height(100.dp)
.background(specialColor.color)
)
}
@Preview
@Composable
fun PreviewSample() {
CustomTheme {
ColorSample(specialColor = SpecialColor.ALPHA)
}
}
Поскольку приведенное выше относится к MaterialTheme.colors вне компонуемого контекста, возникает следующая ошибка:
@Composable invocations can only happen from the context of a @Composable function
Если на цвет ссылаются напрямую, а не через MaterialTheme, цвет не будет правильно обновляться для таких вещей, как светлый/темный режим.
Одной из тактик может быть сопоставление перечисляемых значений с цветами MaterialTheme внутри самой функции @Composable. Но это громоздко, громоздко и плохо масштабируется — представьте себе гораздо более длинный список цветов и тот же список SpecialColor, который нужно повторно использовать для многих функций.
Другая тактика может заключаться в изменении цветов темы напрямую с помощью LocalContentColor или аналогичного, но это слишком широкая кисть и изменит цвета не только для целевой функции.
Возврат цвета из служебной функции @Composable также невозможен, поскольку функции @Composable не имеют возвращаемых значений.
Итак...
Любые мысли о том, как предоставить один из перечисленного списка цветов Compose Material в качестве параметра?
Чистым и расширяемым способом, который хорошо масштабируется?
На самом деле это не так:
@Composable functions don't have return values.
Вы можете аннотировать обе функции с возвращаемыми типами и даже получать только свойства с помощью @Composable
. Например, это является частью исходного кода темы Material.
Вот как вы можете определить свой цвет:
enum class SpecialColor {
ALPHA,
BETA,
;
val color: Color
@Composable
@ReadOnlyComposable
get() = when(this) {
ALPHA -> MaterialTheme.colors.onSurface
BETA -> MaterialTheme.colors.onSecondary
}
}