I've been experimenting with Jetpack compose and I've noticed that although the text colour updates correctly for Text
when you switch to dark mode, the text colour for TextField
or OutlinedTextField
remains stubbornly black. The labels and hint are correctly coloured though.
Having determined that the default text style for the fields is MaterialTheme.typography.body1
I have updated my app theme to include this workaround:
val typography = if (darkTheme) {
//TODO: Hack to show text field text in dark mode
MaterialTheme.typography.copy(body1 = MaterialTheme.typography.body1.copy(color = Color.White))
} else {
MaterialTheme.typography
}
MaterialTheme(colors = colors, content = content, typography = typography)
But if that is the solution I would have to do that for every typography style and it feels like something that should be automatic. So am I doing something wrong, or is this one of those kinks that will be ironed out before it is officially released?
Here is one of my actual Composables (wrapped in my Theme):
@Composable
fun UsernameField(
value: String,
isError: Boolean,
onValueChange: (String) -> Unit,
) {
Column {
OutlinedTextField(
value = value,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth(),
label = { Text("Username") },
isError = isError,
trailingIcon = {
ClearIcon(
visible = value.isNotEmpty(),
onClick = { onValueChange("") }
)
}
)
Text(
if (isError) "Minimum 6 characters" else "",
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.error,
modifier = Modifier.padding(top = 4.dp)
)
}
}
@Composable
fun ClearIcon(visible: Boolean, onClick: () -> Unit) {
if (visible) IconButton(onClick = onClick) {
Icon(
imageVector = Icons.Filled.Cancel,
contentDescription = "Clear username",
)
}
}
Try to wrap it with Surface / apply Surface in composable which uses UsernameField
. To put it simply, you don't have proper background on which text could take proper color configuration to contrast it.
There is short example of possible behaviour and fix:
@Preview
@Composable
fun DarkModeTest() {
MaterialTheme(darkColors()) {
Column {
Surface {
OutlinedTextField(value = "good", onValueChange = {})
}
OutlinedTextField(value = "bad", onValueChange = {})
}
}
}
By looking into docs:
The Surface is responsible for:
...
Content color: Surface uses contentColor to specify a preferred color for the content of this surface - this is used by the Text and Icon components as a default color.