如何为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
相关产品推荐
相关产品推荐

