简体   繁体   English

使 LazyColumn 项目与列表中最大的项目一样大

[英]Make LazyColumn items be as large as the largest item in the list

@Composable
fun PreviewLayout() {
    fun getRandomString(length: Int): String {
        val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
        return (1..length)
            .map { allowedChars.random() }
            .joinToString("")
    }

    val horizontalScrollState = rememberScrollState()

    LazyColumn(
        modifier = Modifier
            .background(Color.Blue)
            .fillMaxHeight()
            .wrapContentWidth()
            .horizontalScroll(horizontalScrollState)
    ) {
        items(5) { index ->
            Text(
                text = getRandomString((index + 1) * 4).uppercase(),
                color = Color.Black,
                fontSize = 16.sp,
                modifier = Modifier
                    .padding(8.dp)
                    .background(Color.Yellow)
            )
        }
    }
}

Preview of the layout:布局预览:

撰写布局预览

I'd like to have the items width be the same as the largest item in the list.我想让项目宽度与列表中最大的项目相同。

Notice the .horizontalScroll(horizontalScrollState) , this is to allow horizontal scrolling.注意.horizontalScroll(horizontalScrollState) ,这是为了允许水平滚动。

What I'd like:我想要什么:

理想的布局预览

I need to use a LazyColumn but if I could use a Column I'd write it this way:我需要使用LazyColumn但如果我可以使用Column我会这样写:

Column(
    modifier = Modifier
        .background(Color.Blue)
        .horizontalScroll(horizontalScrollState)
        .fillMaxHeight()
        .width(IntrinsicSize.Min)
) {
    repeat(5) { index ->
        Text(
            text = getRandomString((index + 1) * 4).uppercase(),
            color = Color.Black,
            fontSize = 16.sp,
            modifier = Modifier
                .padding(8.dp)
                .fillMaxWidth()
                .background(Color.Yellow)
        )
    }
}

This is not possible when horizontal srolling is enabled.当启用水平滚动时,这是不可能的。

Regular Modifier.fillMaxWidth can't work inside the scrolling horizontally layouts as the items are measured with Constraints.Infinity as the constraints for the main axis.常规 Modifier.fillMaxWidth 不能在水平滚动布局内工作,因为项目是使用 Constraints.Infinity 作为主轴的约束来测量的。

If you want your Column solution to work, you need to place it inside another contain (like a Box) and apply horizontal scrolling to the parent.如果您希望您的 Column 解决方案起作用,您需要将它放在另一个包含(如 Box)中并将水平滚动应用于父级。 Scrolling on the Column itself needs to be removed:需要删除滚动列本身:

Box(
    modifier = Modifier
        .requiredWidth(250.dp)
        .fillMaxHeight()
        .horizontalScroll(rememberScrollState())
) {
    Column(
        modifier = Modifier
            .background(Color.Blue)
            .fillMaxHeight()
            .width(IntrinsicSize.Min)

    ) {
        repeat(5) { index ->
            Text(
                text = getRandomString((index + 1) * 40).uppercase(),
                color = Color.Black,
                fontSize = 16.sp,
                modifier = Modifier
                    .padding(8.dp)
                    .fillMaxWidth()
                    .background(Color.Yellow)
            )
        }
    }
}
Column(
    modifier = Modifier
        .background(Color.Blue)
        .horizontalScroll(horizontalScrollState)
        .fillMaxHeight()
        .width(IntrinsicSize.Min)
) {
    repeat(5) { index ->
        Text(
            text = getRandomString((index + 1) * 4).uppercase(),
            color = Color.Black,
            fontSize = 16.sp,
            modifier = Modifier
                .padding(8.dp)
                .width(//*TODO pass here device width*//)
                .background(Color.Yellow)
        )
    }
}
  1. You need to calculate width of the widest element separately.您需要单独计算最宽元素的宽度。 You can do it by placing an invisible copy of you cell with widest content in a Box along with LazyColumn .您可以通过将内容最广泛的单元格的不可见副本与LazyColumn一起放置在Box中来实现。

    In your sample it's easy - just get the longest string.在您的示例中很容易 - 只需获得最长的字符串。 If in the real project you can't decide which of contents is gonna be the widest one, you have two options:如果在实际项目中您无法确定哪个内容将是最广泛的内容,您有两种选择:

    1.1. 1.1。 Place all of them one on top of each other.将它们全部放在一起。 You can do it only if you have some limited number of cells,只有在细胞数量有限的情况下才能做到这一点,

    1.2. 1.2. Otherwise you have to made some approximation and filter a short list of the ones you expect to be the widest ones.否则,您必须进行一些近似并过滤出您期望最广泛的列表。

  2. Because of horizontalScroll maxWidth constraint is infinity, you have to pass calculated width manually.由于horizo horizontalScroll maxWidth约束为无穷大,您必须手动传递计算出的宽度。 You can get it with onSizeChanged :您可以使用onSizeChanged获得它:

@Composable
fun TestScreen(
) {
    fun getRandomString(length: Int): String {
        val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
        return (1..length)
            .map { allowedChars.random() }
            .joinToString("")
    }

    val items = remember {
        List(30) { index ->
            getRandomString((index + 1) * 4).uppercase()
        }
    }
    val maxLengthItem = remember(items) {
        items.maxByOrNull { it.length }
    }
    val (maxLengthItemWidthDp, setMaxLengthItemWidthDp) = remember {
        mutableStateOf<Dp?>(null)
    }

    val horizontalScrollState = rememberScrollState()

    Box(
        Modifier
            .background(Color.Blue)
            .horizontalScroll(horizontalScrollState)
    ) {
        LazyColumn(
            Modifier.fillMaxWidth()
        ) {
            items(items) { item ->
                Cell(
                    item,
                    modifier = if (maxLengthItemWidthDp != null) {
                        Modifier.width(maxLengthItemWidthDp)
                    } else {
                        Modifier
                    }
                )
            }
        }
        if (maxLengthItem != null) {
            val density = LocalDensity.current
            Cell(
                maxLengthItem,
                modifier = Modifier
                    .requiredWidthIn(max = Dp.Infinity)
                    .onSizeChanged {
                        setMaxLengthItemWidthDp(with(density) { it.width.toDp() })
                    }
                    .alpha(0f)
            )
        }
    }
}

@Composable
fun Cell(
    item: String,
    modifier: Modifier,
) {
    Text(
        text = item,
        color = Color.Black,
        fontSize = 16.sp,
        modifier = modifier
            .padding(8.dp)
            .background(Color.Yellow)
    )
}

Result:结果:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM