如何更改 Jetpack Compose 上 TextField 的突出显示文本颜色?

问题描述 投票:0回答:2

目前将我的应用程序转换为 Jetpack compose,在某些情况下我面临着一些调整当前调色板的问题。

我的 xml 文件中有一些

TextInputLayout
,它们继承了主题上次要颜色的突出显示文本颜色。

<style name="Theme.MyApp" parent="Theme.MaterialComponents.Light.NoActionBar">
    ...
    <item name="colorPrimary">@color/blue</item>
    <item name="colorPrimaryVariant">@color/blue</item>
    <item name="colorSecondary">@color/red</item>
    <item name="colorSecondaryVariant">@color/red</item>
    ...
</style>

TextInputLayout with theme's secondary colour - xml

问题是我的撰写中的

TextField
继承了
MaterialTheme
上的主颜色的突出显示文本颜色。

MaterialTheme(
    colors = Colors(
        primary = Color.Blue,
        ...
        secondary = Color.Red,
        ...
    ),
    content = content,
    typography = MaterialTheme.typography,
    shapes = MaterialTheme.shapes,
) {
   TextField(...)
}

TextField with theme's primary color - compose

我覆盖了

colors
上的
TextField
参数,但似乎没有一个影响这种颜色。

是否有一种方法可以在不更改

colors
上的
MaterialTheme
的情况下覆盖构图上的突出显示颜色?我想避免这种情况,因为它可能会在使用相同主题的其他屏幕上引起问题。

android android-jetpack-compose android-textinputlayout android-compose-textfield
2个回答
72
投票

文本和文本字段组件用于文本选择的颜色由

LocalTextSelectionColors.current
提供。

您可以使用以下方式提供自定义

TextSelectionColors

val customTextSelectionColors = TextSelectionColors(
    handleColor = Red,
    backgroundColor = Red.copy(alpha = 0.4f)
)

CompositionLocalProvider(LocalTextSelectionColors provides customTextSelectionColors) {
    TextField(
        value = text,
        onValueChange = { text = it },
        colors = TextFieldDefaults.textFieldColors(cursorColor = Red)
    )
}

如果您还想更改光标颜色,请添加

colors = TextFieldDefaults.textFieldColors(cursorColor = Red)

enter image description here


0
投票

两者:手柄和选择背景都可以在组合本地提供商的帮助下更改。

颜色定义示例(首选

colorTheme
而不是直接使用颜色定义):

val Ecstasy = Color(0xFFF58220)

选择颜色定义:

val selectionColors = TextSelectionColors(
  backgroundColor = Ecstasy.copy(alpha = 0.37f),
  handleColor = Ecstasy
)

它可以与

BasicTextField
(在 Compose 1.7.0-beta 中重命名的
BasicTextField2
)一起使用,但我认为没有理由它不能与
TextField
或任何
MaterialTextField
-s 一起使用。

CompositionLocalProvider(
  LocalTextSelectionColors provides colors.textSelectionColors
) {
  BasicTextField(...)
}

由于每次使用文本字段时都使用组合提供程序可能会很烦人,因此您始终可以考虑实现自己的可组合项。

这正是文档的建议:

使用现成的构建块编写 Jetpack Compose 应用程序,并扩展基础以构建您自己的设计系统组件。

如果可组合功能未按预期工作,始终可以创建一个符合要求的组合。

  • 有一个包含文本字段基础知识的基础层。
  • 有具有材质规范实现的材质层。
  • 您的设计系统级实现可能在幕后使用本地文本选择合成提供程序。

然后就可以使用设计系统级可组合项,而不是直接调用

BasicTextField

最近我创建了一个符合要求的文本字段:

  • 从填充文本字段类型开始(概述了第二个选项)
  • 重新定义形状以不使用任何圆角半径
  • 重置错误指示颜色
  • 为错误状态绘制红色边框
  • 将来它还将用包裹在自己的背景中的自定义设计和顶部的锚点来替换原始的错误文本

结果是:

enter image description here enter image description here

实现方式很简单,如下所示:

fun TextField(
  modifier: Modifier = Modifier,
  state: TextFieldUiState,
  onValueChange: Consumer<String>,
  label: String? = null,
  keyboardActions: KeyboardActions = KeyboardActions(),
  keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
  maxLines: Int = Int.MAX_VALUE,
  singleLine: Boolean = false,
  visualTransformation: VisualTransformation = VisualTransformation.None,
  colors: TextFieldColors = TextFieldDefaults.colors()
) {
  fun TextField(
    modifier: Modifier = Modifier,
    state: TextFieldUiState,
    onValueChange: Consumer<String>,
    label: String? = null,
    keyboardActions: KeyboardActions = KeyboardActions(),
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    maxLines: Int = Int.MAX_VALUE,
    singleLine: Boolean = false,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    colors: TextFieldColors = TextFieldDefaults.colors()
  ) {

    val textStyle =
      TextStyle(color = colors.focusedTextColor)

    val borderWidth = when (state.isError()) {
      true -> 1.dp
      false -> 0.dp
    }

    val borderColor = when (state.isError()) {
      true -> colors.errorIndicatorColor
      false -> Transparent
    }

    CompositionLocalProvider(
      LocalTextSelectionColors provides colors.textSelectionColors
    ) {
      BasicTextField(
        value = state.value,
        onValueChange = onValueChange,
        modifier = modifier.border(
          width = borderWidth,
          color = borderColor
        ),
        enabled = state.enabled,
        keyboardActions = keyboardActions,
        keyboardOptions = keyboardOptions,
        singleLine = singleLine,
        maxLines = maxLines,
        textStyle = textStyle,
        cursorBrush = SolidColor(colors.cursorColor),
        visualTransformation = visualTransformation,
        decorationBox = @Composable { innerTextField ->
          DecorationBox(
            value = state.value,
            visualTransformation = visualTransformation,
            innerTextField = innerTextField,
            label = label?.let { { Text(text = it) } },
            shape = RectangleShape,
            singleLine = singleLine,
            enabled = state.enabled,
            interactionSource = remember { MutableInteractionSource() },
            colors = colors
          )
        }
      )
    }
  }
}

大部分主题是通过

TextFieldDefaults.colors()
的自定义实现完成的。

© www.soinside.com 2019 - 2024. All rights reserved.