Compose笔记(三十九)--文本折叠

         这一节主要了解一下Compose中的文本折叠,在Compose应用开发中,经常会用文本折叠的UI场景,现简单总结:

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

/**
 * 可展开/收起的文本控件
 * @param text 要显示的文本内容
 * @param collapsedMaxLines 折叠状态下最大显示行数
 * @param moreText "更多"文本
 * @param lessText "收起"文本
 * @param textColor 文本颜色
 * @param actionTextColor 操作文本("更多"/"收起")颜色
 */
@Composable
fun TestExpandableText(
    text: String,
    modifier: Modifier = Modifier,
    collapsedMaxLines: Int = 2,
    moreText: String = "更多",
    lessText: String = "收起",
    textColor: Color = Color.Black,
    actionTextColor: Color = Color.Blue
) {
    
    var expanded by remember { mutableStateOf(false) }
    var hasVisualOverflow by remember { mutableStateOf(false) }

    Column(modifier = modifier) {
      
        Text(
            text = text,
            color = textColor,
            fontSize = 16.sp,
            maxLines = if (expanded) Int.MAX_VALUE else collapsedMaxLines,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.fillMaxWidth(),
            onTextLayout = { textLayoutResult ->
                
                hasVisualOverflow = textLayoutResult.hasVisualOverflow
            }
        )

       
        if (hasVisualOverflow) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = if (expanded) lessText else moreText,
                    color = actionTextColor,
                    fontSize = 14.sp,
                    modifier = Modifier
                        .clickable { expanded = !expanded }
                        .padding(end = 4.dp)
                )

                Icon(
                    imageVector = if (expanded) Icons.Filled.KeyboardArrowUp else Icons.Filled.KeyboardArrowDown,
                    contentDescription = if (expanded) "收起" else "更多",
                    tint = actionTextColor,
                    modifier = Modifier.clickable { expanded = !expanded }
                )
            }
        }
    }
}

// 预览
@Composable
fun ExpandableTextPreview() {
    val longText = "这是一段较长的文本内容,用于测试可展开收起功能。当文本内容超过两行时," +
            "会自动显示省略号,并在底部显示'更多'按钮。点击'更多'后,会展示全部文本内容," +
            "同时按钮变为'收起'。再次点击则会折叠回两行显示状态。"

    Column(
        modifier = Modifier
            .padding(16.dp)
            .fillMaxWidth()
    ) {
        Text("短文本示例:", fontSize = 16.sp, fontWeight = androidx.compose.ui.text.font.FontWeight.Bold)
        TestExpandableText(
            text = "这是一段短文本,不会超过两行显示。",
            modifier = Modifier.padding(vertical = 8.dp)
        )

        Text("长文本示例:", fontSize = 16.sp, fontWeight = androidx.compose.ui.text.font.FontWeight.Bold)
        TestExpandableText(
            text = longText,
            modifier = Modifier.padding(vertical = 8.dp)
        )
    }
}

滑动列表自动折叠文本

mport androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.ui.Alignment
import androidx.compose.ui.text.style.TextOverflow


@Composable
fun TestExpandableText(
    text: String,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    collapsedMaxLines: Int = 2,
    moreText: String = "更多",
    lessText: String = "收起",
    textColor: Color = Color.Black,
    actionTextColor: Color = Color.Blue
) {
    var hasOverflow by remember { mutableStateOf(false) }

    Column(modifier = modifier) {
        
        Text(
            text = text,
            color = textColor,
            fontSize = 16.sp,
            maxLines = if (expanded) Int.MAX_VALUE else collapsedMaxLines,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.fillMaxWidth(),
            onTextLayout = { textLayoutResult ->
                
                if (!expanded) {
                    hasOverflow = textLayoutResult.hasVisualOverflow
                }
            }
        )

        
        if (hasOverflow) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = if (expanded) lessText else moreText,
                    color = actionTextColor,
                    fontSize = 14.sp,
                    modifier = Modifier
                        .clickable { onExpandedChange(!expanded) }
                        .padding(end = 4.dp)
                )

                Icon(
                    imageVector = if (expanded) Icons.Filled.KeyboardArrowUp else Icons.Filled.KeyboardArrowDown,
                    contentDescription = if (expanded) "收起" else "更多",
                    tint = actionTextColor,
                    modifier = Modifier.clickable { onExpandedChange(!expanded) }
                )
            }
        }
    }
}


@Composable
fun ScrollAwareExpandableScreen() {
    // 文本内容
    val longText = "这是一段较长的文本内容,用于测试可展开收起功能。当文本内容超过两行时," +
            "会自动显示省略号,并在底部显示'更多'按钮。点击'更多'后,会展示全部文本内容," +
            "同时按钮变为'收起'并且仍然可见。当您滑动下方的列表时,展开的文本会自动折叠。" +
            "再次点击则会折叠回两行显示状态。这是一段较长的文本内容,用于测试可展开收起功能。"

    
    var textExpanded by remember { mutableStateOf(false) }

    
    val listState = rememberLazyListState()

    
    LaunchedEffect(listState.isScrollInProgress) {
        if (listState.isScrollInProgress && textExpanded) {
            textExpanded = false
        }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        // 上部:可展开文本
        TestExpandableText(
            text = longText,
            expanded = textExpanded,
            onExpandedChange = { textExpanded = it },
            modifier = Modifier.padding(bottom = 16.dp)
        )

        // 下部:列表
        Text(
            text = "列表内容:",
            fontSize = 16.sp,
            fontWeight = androidx.compose.ui.text.font.FontWeight.Bold,
            modifier = Modifier.padding(bottom = 8.dp)
        )

        LazyColumn(
            state = listState,
            modifier = Modifier.fillMaxSize()
        ) {
            items(50) { index ->
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(60.dp)
                        .padding(vertical = 4.dp)
                        .background(Color.LightGray.copy(alpha = 0.3f)),
                    contentAlignment = Alignment.Center
                ) {
                    Text(text = "列表项 ${index + 1}")
                }
            }
        }
    }
}

// 预览
@Composable
fun TestScrollAwareExpandableScreenPreview() {
    ScrollAwareExpandableScreen()
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值