You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Jetpack Compose Selection Container添加自定义操作?

为Jetpack Compose SelectionContainer添加自定义选择操作

要在Compose的SelectionContainer中添加分享、高亮等自定义选项,核心是通过**自定义TextSelectionControls**替换默认的选择控制器,具体实现步骤如下:

1. 实现自定义文本选择控制器

通过继承DefaultTextSelectionControls,重写菜单项生成逻辑,添加自定义操作:

import androidx.compose.foundation.text.selection.DefaultTextSelectionControls
import androidx.compose.foundation.text.selection.TextSelectionControls
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.filled.Highlight
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable

// 自定义选择控制器,接受外部状态与操作回调
@Composable
fun customTextSelectionControls(
    onShareClicked: () -> Unit,
    onHighlightClicked: () -> Unit
): TextSelectionControls {
    return object : DefaultTextSelectionControls() {
        @Composable
        override fun getMenuItems(
            onCopyRequested: () -> Unit,
            onPasteRequested: () -> Unit,
            onCutRequested: () -> Unit,
            onSelectAllRequested: () -> Unit,
        ): List<@Composable () -> Unit> {
            // 保留默认的复制等系统选项
            val defaultMenuItems = super.getMenuItems(
                onCopyRequested, onPasteRequested, onCutRequested, onSelectAllRequested
            )

            return buildList {
                // 添加分享选项
                add {
                    TextSelectionMenuItem(
                        label = { Text("分享") },
                        icon = { Icon(Icons.Default.Share, contentDescription = "分享选中文本") },
                        onClick = onShareClicked
                    )
                }
                // 添加高亮选项
                add {
                    TextSelectionMenuItem(
                        label = { Text("高亮") },
                        icon = { Icon(Icons.Default.Highlight, contentDescription = "高亮选中文本") },
                        onClick = onHighlightClicked
                    )
                }
                // 追加系统默认选项
                addAll(defaultMenuItems)
            }
        }
    }
}

// 复用Compose内置的菜单项样式组件
@Composable
private fun TextSelectionMenuItem(
    label: @Composable () -> Unit,
    icon: @Composable () -> Unit,
    onClick: () -> Unit
) {
    androidx.compose.foundation.text.selection.TextSelectionMenuItem(
        onClick = onClick,
        icon = icon,
        text = label
    )
}

2. 在SelectionContainer中集成自定义控制器

修改你的PoemVerse组件,管理选中文本状态,绑定自定义控制器并实现操作逻辑:

import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.core.app.ShareCompat

@Composable
fun PoemVerse() {
    val context = LocalContext.current
    // 记录当前选中的文本
    val selectedText = remember { mutableStateOf("") }
    // 记录需要高亮的文本
    val highlightedText = remember { mutableStateOf("") }
    val fullVerseText = "This is a sample verse from a poem."

    // 初始化自定义选择控制器
    val customSelectionControls = customTextSelectionControls(
        onShareClicked = {
            // 调用系统分享面板
            ShareCompat.IntentBuilder(context)
                .setType("text/plain")
                .setText(selectedText.value)
                .startChooser()
        },
        onHighlightClicked = {
            // 将选中文本标记为高亮
            highlightedText.value = selectedText.value
        }
    )

    SelectionContainer(
        selectionControls = customSelectionControls,
        // 监听选中范围变化,更新选中文本状态
        onSelectionChange = { selection ->
            selection?.let {
                selectedText.value = fullVerseText.substring(it.start, it.end)
            } ?: run {
                selectedText.value = ""
            }
        }
    ) {
        // 构建带高亮样式的文本
        val annotatedVerse = buildAnnotatedString {
            append(fullVerseText)
            if (highlightedText.value.isNotEmpty()) {
                val startIndex = fullVerseText.indexOf(highlightedText.value)
                if (startIndex != -1) {
                    addStyle(
                        style = SpanStyle(background = Color.Yellow.copy(alpha = 0.3f)),
                        start = startIndex,
                        end = startIndex + highlightedText.value.length
                    )
                }
            }
        }
        Text(text = annotatedVerse)
    }
}

关键逻辑说明

  • 选中文本监听:通过SelectionContainer的onSelectionChange回调获取选中范围,提取对应文本存入状态,供后续操作使用。
  • 高亮实现:使用AnnotatedString为指定文本段添加背景色样式,结合状态动态更新高亮内容。
  • 分享功能:借助AndroidX的ShareCompat构建分享Intent,唤起系统分享面板。
  • 样式一致性:复用Compose内置的TextSelectionMenuItem组件,保证自定义菜单与系统默认菜单样式统一。

内容的提问来源于stack exchange,提问作者EfM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 04:45:17