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时,仅当前可见的文本项可被选择,滑动后新渲染的项需重新触发选择操作。

相关推荐
一隅论数智2 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
深圳老胡3 天前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android