将 Material3 颜色应用于 Jetpack Compose 中的 OutlinedTextField
Applying Material3 colors to OutlinedTextField in Jetpack Compose
编辑:添加更多细节 - 使代码完整:
在转换为新的 M3 主题后,我在将主题颜色应用于 OutlinedTextFields
时遇到了挑战。
据我所知,在使用 OutlinedTextField
.[=24 时,不直接支持使用新的设计标记颜色(primaryContainer
、tertiary
等) =]
问题:有没有一种简单的方法可以通用地应用这些颜色?
问题:当我应用自定义颜色时,它们并没有全部应用,我不确定为什么?
我尝试了什么:
这是我用来创建自定义 TextFieldColors
的函数,以及我如何应用它们:
@Composable
fun customTextColors(): TextFieldColors =
TextFieldDefaults.outlinedTextFieldColors(
textColor = MaterialTheme.colorScheme.onBackground,
disabledTextColor = MaterialTheme.colorScheme.onBackground,
backgroundColor = MaterialTheme.colorScheme.background,
cursorColor = MaterialTheme.colorScheme.onBackground,
errorCursorColor = MaterialTheme.colorScheme.error,
focusedBorderColor = MaterialTheme.colorScheme.primary,
unfocusedBorderColor = MaterialTheme.colorScheme.onBackground,
disabledBorderColor = MaterialTheme.colorScheme.onBackground,
errorBorderColor = MaterialTheme.colorScheme.error,
leadingIconColor = MaterialTheme.colorScheme.onBackground,
disabledLeadingIconColor = MaterialTheme.colorScheme.onBackground,
errorLeadingIconColor = MaterialTheme.colorScheme.error,
trailingIconColor = MaterialTheme.colorScheme.onBackground,
disabledTrailingIconColor = MaterialTheme.colorScheme.onBackground,
errorTrailingIconColor = MaterialTheme.colorScheme.error,
focusedLabelColor = MaterialTheme.colorScheme.primary,
unfocusedLabelColor = MaterialTheme.colorScheme.onBackground,
disabledLabelColor = MaterialTheme.colorScheme.onBackground,
errorLabelColor = MaterialTheme.colorScheme.error,
placeholderColor = MaterialTheme.colorScheme.onBackground,
disabledPlaceholderColor = MaterialTheme.colorScheme.primary,
)
然后以这种方式应用它们:
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.outlined.Visibility
import androidx.compose.material.icons.outlined.VisibilityOff
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.input.*
import com.myApp.demo.R
import com.myApp.demo.data.StaticData
import com.myApp.demo.ui.theme.card_corner_radius
import com.myApp.demo.ui.theme.grey_400
import com.myApp.demo.ui.theme.horizfull_verthalf
@Composable
fun NameTextInput(name: String, onNameInfoValid: (Boolean) -> Unit) {
// Name
val nameState = remember { mutableStateOf(TextFieldValue(name)) }
val nameString = stringResource(R.string.name)
val nameLabelState = remember { mutableStateOf(nameString) }
val isNameValid = if (nameState.value.text.length >= 5) {
nameLabelState.value = nameString
onNameInfoValid(true)
true
} else {
nameLabelState.value = stringResource(R.string.name_error)
onNameInfoValid(false)
false
}
OutlinedTextField(
shape = RoundedCornerShape(card_corner_radius),
value = nameState.value,
singleLine = true,
onValueChange = { if (it.text.length <= 30) nameState.value = it },
isError = !isNameValid,
label = { Text(nameLabelState.value) },
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
capitalization = KeyboardCapitalization.Words
),
colors = customTextColors(), // <-- Here is where colors are set!
modifier = Modifier
.fillMaxWidth()
.padding(horizfull_verthalf)
)
}
没有全部被应用。
我看到 focusedBorderColor
设置正确,但我没有看到 focusedLabelColor
被正确应用(在这种情况下,红色是正确的 primary 颜色被应用,所以我希望看到标签也是红色的)
另外错误是 border 有效,但不适用于其他属性:
这是我的主题设置:
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
private val DarkColorPalette = darkColorScheme(
primary = grey_700,
onPrimary = white_desat,
tertiary = grey_600,
secondary = amer_blue, // TODO desat
onSecondary = grey_500,
surface = black_pure,
onSurface = white_desat,
surfaceVariant = grey_800,
onSurfaceVariant = white_desat,
error = orange_700,
onError = orange_700
)
private val LightColorPalette = lightColorScheme(
primary = amer_red,
onPrimary = white_pure,
tertiary = amer_blue_50,
secondary = amer_blue,
onSecondary = grey_500,
surface = white_pure,
onSurface = black_pure,
surfaceVariant = white_pure,
onSurfaceVariant = black_pure,
error = orange_500,
onError = orange_500,
errorContainer = orange_500,
onErrorContainer = orange_500
/* Other default colors to override
background = Color.White,
onBackground = Color.Black,
*/
)
@Composable
fun ComposeTemplateTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colorScheme = colors,
typography = DemoTypography,
content = content
)
}
最后为了使这个示例完整,这里是我首先调用可组合项的方式:
NameTextInput(name = personalInfo.name, onNameInfoValid = { isNameValidState.value = it })
...以及我使用的版本
appCompatVersion = '1.3.1'
activityComposeVersion = '1.4.0'
composeVersion = '1.0.4'
composeNavigationVersion = '2.4.0-alpha06'
kotlinVersion = '1.5.31'
ktlint_version = "0.42.1"
ktxVersion = '1.7.0'
lifecycleVersion = '2.3.0'
materialVersion = '1.5.0-alpha05'
这看起来很疯狂。但这就是发生的事情。
Material 2 和 Material 3 之间似乎存在一些风格冲突。 (我猜显然很明显)。
正在使用
import androidx.compose.material3.Text
但是当使用
import androidx.compose.material.Text
这一行更改解决了问题。
如果需要,我的完整 material 导入。
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Clear
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
其他有用的信息,
我正在维护完整的 2 套资源。
这可能有助于 M3 尚不支持的组件。
在可组合项中使用适当的导入。
如果特定可组合项同时具有 M2 和 M3 组件,我们可以使用完整导入。
private val Material2DarkColorPalette = darkColors(
primary = Primary,
...
)
private val Material2LightColorPalette = lightColors(
primary = Primary,
...
)
private val LightColorPalette = lightColorScheme(
primary = Primary,
...
)
private val DarkColorPalette = darkColorScheme(
primary = Primary,
...
)
@Composable
fun Material2AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val colors = if (darkTheme) {
Material2DarkColorPalette
} else {
Material2LightColorPalette
}
androidx.compose.material.MaterialTheme(
colors = colors,
typography = Material2Typography,
shapes = Shapes,
content = content
)
}
@Composable
fun Material3AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colorScheme = colors,
typography = Typography,
content = content
)
}
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
Material2AppTheme(
darkTheme = darkTheme,
content = content,
)
}
编辑:添加更多细节 - 使代码完整:
在转换为新的 M3 主题后,我在将主题颜色应用于 OutlinedTextFields
时遇到了挑战。
据我所知,在使用 OutlinedTextField
.[=24 时,不直接支持使用新的设计标记颜色(primaryContainer
、tertiary
等) =]
问题:有没有一种简单的方法可以通用地应用这些颜色?
问题:当我应用自定义颜色时,它们并没有全部应用,我不确定为什么?
我尝试了什么:
这是我用来创建自定义 TextFieldColors
的函数,以及我如何应用它们:
@Composable
fun customTextColors(): TextFieldColors =
TextFieldDefaults.outlinedTextFieldColors(
textColor = MaterialTheme.colorScheme.onBackground,
disabledTextColor = MaterialTheme.colorScheme.onBackground,
backgroundColor = MaterialTheme.colorScheme.background,
cursorColor = MaterialTheme.colorScheme.onBackground,
errorCursorColor = MaterialTheme.colorScheme.error,
focusedBorderColor = MaterialTheme.colorScheme.primary,
unfocusedBorderColor = MaterialTheme.colorScheme.onBackground,
disabledBorderColor = MaterialTheme.colorScheme.onBackground,
errorBorderColor = MaterialTheme.colorScheme.error,
leadingIconColor = MaterialTheme.colorScheme.onBackground,
disabledLeadingIconColor = MaterialTheme.colorScheme.onBackground,
errorLeadingIconColor = MaterialTheme.colorScheme.error,
trailingIconColor = MaterialTheme.colorScheme.onBackground,
disabledTrailingIconColor = MaterialTheme.colorScheme.onBackground,
errorTrailingIconColor = MaterialTheme.colorScheme.error,
focusedLabelColor = MaterialTheme.colorScheme.primary,
unfocusedLabelColor = MaterialTheme.colorScheme.onBackground,
disabledLabelColor = MaterialTheme.colorScheme.onBackground,
errorLabelColor = MaterialTheme.colorScheme.error,
placeholderColor = MaterialTheme.colorScheme.onBackground,
disabledPlaceholderColor = MaterialTheme.colorScheme.primary,
)
然后以这种方式应用它们:
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.outlined.Visibility
import androidx.compose.material.icons.outlined.VisibilityOff
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.input.*
import com.myApp.demo.R
import com.myApp.demo.data.StaticData
import com.myApp.demo.ui.theme.card_corner_radius
import com.myApp.demo.ui.theme.grey_400
import com.myApp.demo.ui.theme.horizfull_verthalf
@Composable
fun NameTextInput(name: String, onNameInfoValid: (Boolean) -> Unit) {
// Name
val nameState = remember { mutableStateOf(TextFieldValue(name)) }
val nameString = stringResource(R.string.name)
val nameLabelState = remember { mutableStateOf(nameString) }
val isNameValid = if (nameState.value.text.length >= 5) {
nameLabelState.value = nameString
onNameInfoValid(true)
true
} else {
nameLabelState.value = stringResource(R.string.name_error)
onNameInfoValid(false)
false
}
OutlinedTextField(
shape = RoundedCornerShape(card_corner_radius),
value = nameState.value,
singleLine = true,
onValueChange = { if (it.text.length <= 30) nameState.value = it },
isError = !isNameValid,
label = { Text(nameLabelState.value) },
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
capitalization = KeyboardCapitalization.Words
),
colors = customTextColors(), // <-- Here is where colors are set!
modifier = Modifier
.fillMaxWidth()
.padding(horizfull_verthalf)
)
}
没有全部被应用。
我看到 focusedBorderColor
设置正确,但我没有看到 focusedLabelColor
被正确应用(在这种情况下,红色是正确的 primary 颜色被应用,所以我希望看到标签也是红色的)
另外错误是 border 有效,但不适用于其他属性:
这是我的主题设置:
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
private val DarkColorPalette = darkColorScheme(
primary = grey_700,
onPrimary = white_desat,
tertiary = grey_600,
secondary = amer_blue, // TODO desat
onSecondary = grey_500,
surface = black_pure,
onSurface = white_desat,
surfaceVariant = grey_800,
onSurfaceVariant = white_desat,
error = orange_700,
onError = orange_700
)
private val LightColorPalette = lightColorScheme(
primary = amer_red,
onPrimary = white_pure,
tertiary = amer_blue_50,
secondary = amer_blue,
onSecondary = grey_500,
surface = white_pure,
onSurface = black_pure,
surfaceVariant = white_pure,
onSurfaceVariant = black_pure,
error = orange_500,
onError = orange_500,
errorContainer = orange_500,
onErrorContainer = orange_500
/* Other default colors to override
background = Color.White,
onBackground = Color.Black,
*/
)
@Composable
fun ComposeTemplateTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colorScheme = colors,
typography = DemoTypography,
content = content
)
}
最后为了使这个示例完整,这里是我首先调用可组合项的方式:
NameTextInput(name = personalInfo.name, onNameInfoValid = { isNameValidState.value = it })
...以及我使用的版本
appCompatVersion = '1.3.1'
activityComposeVersion = '1.4.0'
composeVersion = '1.0.4'
composeNavigationVersion = '2.4.0-alpha06'
kotlinVersion = '1.5.31'
ktlint_version = "0.42.1"
ktxVersion = '1.7.0'
lifecycleVersion = '2.3.0'
materialVersion = '1.5.0-alpha05'
这看起来很疯狂。但这就是发生的事情。
Material 2 和 Material 3 之间似乎存在一些风格冲突。 (我猜显然很明显)。
正在使用
import androidx.compose.material3.Text
但是当使用
import androidx.compose.material.Text
这一行更改解决了问题。
如果需要,我的完整 material 导入。
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Clear
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
其他有用的信息,
我正在维护完整的 2 套资源。
这可能有助于 M3 尚不支持的组件。
在可组合项中使用适当的导入。
如果特定可组合项同时具有 M2 和 M3 组件,我们可以使用完整导入。
private val Material2DarkColorPalette = darkColors(
primary = Primary,
...
)
private val Material2LightColorPalette = lightColors(
primary = Primary,
...
)
private val LightColorPalette = lightColorScheme(
primary = Primary,
...
)
private val DarkColorPalette = darkColorScheme(
primary = Primary,
...
)
@Composable
fun Material2AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val colors = if (darkTheme) {
Material2DarkColorPalette
} else {
Material2LightColorPalette
}
androidx.compose.material.MaterialTheme(
colors = colors,
typography = Material2Typography,
shapes = Shapes,
content = content
)
}
@Composable
fun Material3AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colorScheme = colors,
typography = Typography,
content = content
)
}
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
Material2AppTheme(
darkTheme = darkTheme,
content = content,
)
}