Compose笔记(六十一)--SelectionContainer

这一节主要了解一下Compose中的SelectionContainer,SelectionContainer是Jetpack Compose中用于启用内容文本选择功能的容器组件,它的核心作用是让其子组件中的文本支持长按选中、复制、粘贴、剪切等系统默认的文本操作,简单总结如下:

场景:

1 长文本阅读与编辑,在文章阅读、消息列表等场景中,用户可能需要复制部分内容。

2 表单或输入界面,当用户需要从预填充的文本中复制部分内容时,SelectionContainer可提升操作便捷性。

3 层级数据选择,在树形结构或列表中,若父节点需反映子节点的部分选中状态,可结合TriStateCheckbox和SelectionContainer实现更复杂的交互。

栗子:

Kotlin 复制代码
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SelectionContainerDemo() {

    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("SelectionContainerDemo") },
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer
                )
            )
        }
    ) { padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .padding(16.dp)
        ) {
           
            Text(
                text = "我是普通文本,长按无法选中",
                style = MaterialTheme.typography.bodyLarge
            )

            Spacer(modifier = Modifier.height(20.dp))

           
            SelectionContainer {
                Text(
                    text = "我是可选中的文本,长按试试?\n支持换行文本的选中哦~",
                    style = MaterialTheme.typography.bodyLarge
                )
            }

            Spacer(modifier = Modifier.height(20.dp))

            
            SelectionContainer {
                Column {
                    Text(
                        text = "这是第一段可选中的文本",
                        style = MaterialTheme.typography.bodyLarge
                    )
                    Text(
                        text = "这是第二段可选中的文本,能和上段文本一起被选中",
                        style = MaterialTheme.typography.bodyLarge
                    )
                }
            }
        }
    }
}
Kotlin 复制代码
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.DisableSelection
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Divider
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

data class Article(
    val title: String,
    val author: String,
    val publishTime: String,
    val content: List<String>, 
    val quote: String,
    val codeBlock: String 
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SelectionContainerDemo2() {
   
    val article = remember {
        Article(
            title = "Compose中SelectionContainer的Demo",
            author = "Compose笔记",
            publishTime = "2025-12-14",
            content = listOf(
                "SelectionContainer是Jetpack Compose中用于启用文本选择功能的核心容器组件,它可以让子组件中的文本支持长按选中、复制、粘贴等系统默认操作。",
                "与普通Text组件不同,默认情况下Text组件是不支持文本选择的,必须包裹在SelectionContainer中才能启用该功能。"
            ),
            quote = "重点:SelectionContainer支持跨组件选中文本,多个Text组件包裹在同一个SelectionContainer中时,用户可以连续选中所有文本。",
            codeBlock = "// 示例代码\nSelectionContainer {\n    Text(text = \"可选中的文本\")\n}\n\nDisableSelection {\n    Text(text = \"不可选中的文本\")\n}"
        )
    }

   
    androidx.compose.foundation.lazy.LazyColumn(
        modifier = Modifier.fillMaxSize(),
        contentPadding = PaddingValues(horizontal = 16.dp, vertical = 20.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
       
        item {
            DisableSelection {
                Column(
                    modifier = Modifier.fillMaxWidth(),
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                   
                    Text(
                        text = article.title,
                        fontSize = 24.sp,
                        fontWeight = FontWeight.Bold,
                        color = MaterialTheme.colorScheme.onBackground
                    )
                    
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.SpaceBetween,
                        verticalAlignment = Alignment.CenterVertically
                    ) {
                        Text(
                            text = "作者:${article.author}",
                            fontSize = 14.sp,
                            color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f)
                        )
                        Text(
                            text = article.publishTime,
                            fontSize = 14.sp,
                            color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f)
                        )
                    }
                   
                    Divider(
                        color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.1f),
                        thickness = 1.dp
                    )
                }
            }
        }

        
        item {
            SelectionContainer {
                Column(
                    modifier = Modifier.fillMaxWidth(),
                    verticalArrangement = Arrangement.spacedBy(12.dp)
                ) {
                    article.content.forEach { paragraph ->
                        Text(
                            text = paragraph,
                            fontSize = 16.sp,
                            lineHeight = 24.sp,
                        )
                    }
                }
            }
        }
   
        item {
            SelectionContainer {
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(8.dp),
                    border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary.copy(alpha = 0.3f)),
                    colors = CardDefaults.cardColors(
                        containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.05f)
                    )
                ) {
                    Text(
                        text = article.quote,
                        modifier = Modifier.padding(16.dp),
                        fontSize = 16.sp,
                        lineHeight = 24.sp,
                        color = MaterialTheme.colorScheme.primary
                    )
                }
            }
        }
      
        item {
            DisableSelection {
                Card(
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(8.dp),
                    colors = CardDefaults.cardColors(
                        containerColor = Color(0xFFF5F5F5)
                    )
                ) {
                    Text(
                        text = article.codeBlock,
                        modifier = Modifier.padding(16.dp),
                        fontSize = 14.sp,
                        lineHeight = 20.sp,
                        color = Color(0xFF333333)
                    )
                }
            }
        }
    }
}

注意:

1 避免在SelectionContainer中包裹大量文本或复杂布局,未渲染的文本项不会被包含在选择操作中,且可能影响性能。

2 与DisableSelection配合 若需禁止部分文本的选择,用DisableSelection包裹目标组件。

3 懒加载布局的兼容性 在LazyColumn或LazyRow中使用SelectionContainer时,仅当前可见的文本项可被选择,滑动后新渲染的项需重新触发选择操作。

相关推荐
阿拉斯攀登3 分钟前
【无人售货柜・RK+YOLO】篇 6:安卓端落地!RK3576 + 安卓系统,YOLO RKNN 模型实时推理保姆级教程
android·人工智能·yolo·目标跟踪·瑞芯微·嵌入式驱动
421!14 分钟前
ESP32学习笔记之GPIO
开发语言·笔记·单片机·嵌入式硬件·学习·算法·fpga开发
Flittly16 分钟前
【从零手写 ClaudeCode:learn-claude-code 项目实战笔记】(10)Team Protocols (团队协议)
笔记·python·ai·ai编程
只能是遇见27 分钟前
ERROR 1524 (HY000) Plugin ‘mysql_native_password‘ is not loaded
android·数据库·mysql
-Excalibur-29 分钟前
IP数据包在计算机网络传输的全过程
java·网络·c++·笔记·python·网络协议·智能路由器
读忆44 分钟前
你是否用过Tailwind CSS?你是在什么情况下使用的呢?
前端·css·经验分享·笔记·taiiwindcss
sheeta19981 小时前
苍穹外卖Day07笔记
笔记
左左右右左右摇晃1 小时前
String、StringBuffer、StringBuilder的区别
java·笔记
helloworddm1 小时前
第一篇:设计模式在 Android 视频播放器中的实战应用
android·设计模式·音视频
恋猫de小郭1 小时前
Android 禁止侧载将正式实施,需要等待 24 小时冷静期
android·flutter·harmonyos