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

Compose实现自适应文本宽度的可选中垂直网格布局需求

在Jetpack Compose中实现自适应文本宽度的可选中流式网格布局

要实现无固定列数、单元格自适应文本宽度且支持选中状态的布局,最直接的方案是使用Compose Material3中的FlowRow组件,它天然支持流式自动换行,配合状态管理即可实现需求。

核心实现代码

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.FlowRow
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

// 传入后端返回的文本列表,渲染自适应流式网格
@Composable
fun AdaptiveSelectableGrid(items: List<String>) {
    // 单选状态管理,如需多选可替换为mutableStateSetOf<String>()
    val selectedItem = remember { mutableStateOf<String?>(null) }

    FlowRow(
        modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
        // 控制单元格之间的水平、垂直间距
        horizontalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(8.dp),
        verticalArrangement = androidx.compose.foundation.layout.Arrangement.spacedBy(8.dp)
    ) {
        items.forEach { item ->
            val isSelected = selectedItem.value == item
            // 根据选中状态切换样式
            val cellBackground = if (isSelected) {
                MaterialTheme.colorScheme.primaryContainer
            } else {
                MaterialTheme.colorScheme.surfaceVariant
            }
            val textColor = if (isSelected) {
                MaterialTheme.colorScheme.onPrimaryContainer
            } else {
                MaterialTheme.colorScheme.onSurfaceVariant
            }

            Text(
                text = item,
                modifier = Modifier
                    .background(cellBackground, RoundedCornerShape(8.dp))
                    .clickable {
                        // 点击切换选中状态,单选逻辑:再次点击取消选中
                        selectedItem.value = if (isSelected) null else item
                    }
                    .padding(horizontal = 12.dp, vertical = 8.dp),
                color = textColor,
                maxLines = 1 // 强制单行文本,保证宽度由内容自适应
            )
        }
    }
}

关键逻辑说明

  1. 流式布局实现:FlowRow会自动根据子项的宽度计算每行可容纳的单元格数量,完全适配无固定列数的需求,无需提前计算列数。
  2. 自适应宽度:Text组件默认会根据文本内容测量自身宽度,因此每个单元格的宽度会自动匹配文本长度,无需手动设置固定宽度。
  3. 选中状态管理:通过remember和mutableStateOf保存选中项,确保状态在重组时得以保留,点击事件触发状态切换。
  4. 样式区分:利用Material3的主题色体系,根据选中状态切换单元格背景和文本颜色,保证样式统一且符合Material Design规范。

扩展调整

  • 多选支持:如果需要多选功能,只需将selectedItem替换为val selectedItems = remember { mutableStateSetOf<String>() },点击事件改为:
    clickable {
        if (isSelected) selectedItems.remove(item) else selectedItems.add(item)
    }
    
    同时将isSelected的判断改为selectedItems.contains(item)。
  • 样式自定义:可以根据需求调整FlowRow的间距、单元格的padding、圆角大小,或者替换自定义的背景色、文本样式。
  • 超长文本处理:如果存在超出屏幕宽度的文本,可以给Text添加Modifier.horizontalScroll(rememberScrollState())实现横向滚动,或者调整字体大小避免溢出。

内容的提问来源于stack exchange,提问作者Сергей Беляков

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:32:54