ITmob-Ly
发布于 2023-08-28 / 183 阅读
0

Jetpack Compose 中怎样隐藏或禁用 TextField(文本字段)的光标、文本选择手柄和文本工具栏?

前言

本文介绍文本字段 TextField 中怎样隐藏光标、选择手柄、文本工具栏。实现这几个功能首先我们先来了解下 TextField 相关的几个属性:

  1. cursorBrush

    使用 Brash 绘制光标。如果提供了颜色值为 Color.UnspecifiedSolidColor,则不会绘制光标。

  2. LocalTextSelectionColors

    用于更改层次结构中文本和文本字段组件使用的 TextSelectionColors

  3. LocalTextToolbar

    提供文本工具栏的 CompositionLocal

TextField 默认效果

@Composable
fun TextFieldSample() {
    var text by remember { mutableStateOf("https://itmob.cn") }
    BasicTextField(
        value = text,
        onValueChange = {
            text = it
        },
        modifier = Modifier
            .fillMaxWidth()
            .clip(MaterialTheme.shapes.medium)
            .background(MaterialTheme.colorScheme.primaryContainer)
            .padding(16.dp),
        singleLine = true,
        textStyle = TextStyle(
            fontSize = 22.sp,
            fontWeight = FontWeight.Bold,
            textAlign = TextAlign.Center,
        ),
    )
}

上面的代码是未修改文本光标及工具栏相关功能的效果:

Default TextToolbar

隐藏光标

  1. BasicTextField 中,使用 cursorBrush = SolidColor(Color.Unspecified) 隐藏光标。
  2. TextField 中,使用属性 colors = TextFieldDefaults.textFieldColors(cursorColor = Color.Unspecified)
@Composable
fun TextFieldWithHidingCursor() {
    var text by remember { mutableStateOf("https://itmob.cn") }
    BasicTextField(
        value = text,
        onValueChange = {
            text = it
        },
        // 隐藏光标
        cursorBrush = SolidColor(Unspecified),
        modifier = Modifier
            .fillMaxWidth()
            .clip(MaterialTheme.shapes.medium)
            .background(MaterialTheme.colorScheme.primaryContainer)
            .padding(16.dp),
        singleLine = true,
        textStyle = TextStyle(
            fontSize = 22.sp,
            fontWeight = FontWeight.Bold,
            textAlign = TextAlign.Center,
        ),
    )
    TextField(
        value = text,
        onValueChange = {
            text = it
        },
        // 隐藏光标
        colors = TextFieldDefaults.colors(cursorColor = Unspecified),
        modifier = Modifier
            .fillMaxWidth()
            .clip(MaterialTheme.shapes.medium)
            .background(MaterialTheme.colorScheme.primaryContainer)
            .padding(16.dp),
        singleLine = true,
        textStyle = TextStyle(
            fontSize = 22.sp,
            fontWeight = FontWeight.Bold,
            textAlign = TextAlign.Center,
        ),
    )
}

cursorColor = Unspecified 不会绘制光标,但是点击文本还是可以修改文本的输入位置的,只是光标不显示

隐藏文本选择效果(选择手柄,被选文本的背景)

选择手柄是选择文本时两个水滴状的手柄

Default selection colors

@Composable
fun TextFieldWithoutSelectionColors() {
    var text by remember { mutableStateOf("https://itmob.cn") }

    // 设置自定义的 TextSelectionColors 将选择手柄和背景设置为透明色
    val customSelectionColors = TextSelectionColors(
        handleColor = Transparent,
        backgroundColor = Transparent,
    )
    CompositionLocalProvider(
        LocalTextSelectionColors provides customSelectionColors,
    ) {
        BasicTextField(
            value = text,
            onValueChange = {
                text = it
            },
            singleLine = true,
            textStyle = TextStyle(
                fontSize = 22.sp,
                fontWeight = FontWeight.Bold,
                textAlign = TextAlign.Center,
            ),
            modifier = Modifier
                .fillMaxWidth()
                .clip(MaterialTheme.shapes.medium)
                .background(MaterialTheme.colorScheme.primaryContainer)
                .padding(16.dp),
        )
    }
}

下图是隐藏选择手柄和选择文本背景的效果,该方法可以隐藏选择效果但并不能禁止选择

Transparent selection colors

禁用文本工具栏

// 定义一个空实现的 TextToolbar
object EmptyTextToolbar : TextToolbar {
    override val status: TextToolbarStatus = TextToolbarStatus.Hidden

    override fun hide() { }

    override fun showMenu(
        rect: Rect,
        onCopyRequested: (() -> Unit)?,
        onPasteRequested: (() -> Unit)?,
        onCutRequested: (() -> Unit)?,
        onSelectAllRequested: (() -> Unit)?,
    ) {
    }
}

@Composable
fun TextFieldWithoutTextToolbar() {
    var text by remember { mutableStateOf("https://itmob.cn") }
    CompositionLocalProvider(
        // 设置空实现的 TextToolbar 来禁用文本工具栏
        LocalTextToolbar provides EmptyTextToolbar,
    ) {
        BasicTextField(
            value = text,
            onValueChange = {
                text = it
            },
            modifier = Modifier
                .fillMaxWidth()
                .clip(MaterialTheme.shapes.medium)
                .background(MaterialTheme.colorScheme.primaryContainer)
                .padding(16.dp),
            singleLine = true,
            textStyle = TextStyle(
                fontSize = 22.sp,
                fontWeight = FontWeight.Bold,
                textAlign = TextAlign.Center,
            ),
        )
    }
}

Disable TextToolbar