kotlin 如何知道组合的相对位置时,给它一个自定义的布局?

9jyewag0  于 2023-10-23  发布在  Kotlin
关注(0)|答案(1)|浏览(125)

我试图创建一个自定义的Composes布局,其中元素(主要在Column中)的最大宽度取决于它们在父元素中的位置。
我已经提出了以下Modifier来实现它:

fun Modifier.widthDependingOnTop() = composed {
    var parentY by remember { mutableFloatStateOf(Float.NaN) }
    onPlaced {
        parentY = it.positionInParent().y
    }.layout { measurable, constraints ->
        val placeable = measurable.measure(
            if (parentY <= 200f) {
                constraints.copy(maxWidth = 100)
            } else {
                constraints
            }
        )
        layout(placeable.width, placeable.height) {
            placeable.placeRelative(x = 0, y = 0)
        }
    }
}

我是这样使用它的:

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    repeat(5) {
        Row(Modifier.widthDependingOnTop().background(Color.Red)) {
            Text("lorem ipsum")
        }
    }
}

它产生了预期的结果:

然而,这并不理想,因为内容在显示时会短暂 Flink -我理解这是因为我在等待onPlaced知道父对象内部的坐标,之后我修改了宽度(可能)。
如果在layout{}内部有一种方法可以知道可组合对象在父对象中的位置,我就可以避免这种情况,但是我找不到类似的方法。有没有办法做到这一点?也许应该对父Column而不是子Column应用一个修改器?

bzzcjhmw

bzzcjhmw1#

如果您不希望Composable像this answer中那样在大小更改时重新组合,则可以将此逻辑移动到Layout中。
但是,如果你想继续使用修改器,你可以通过使用Modiifer.drawWithContent{drawContent()}的条件来延迟绘制一个或几个帧。
要等待一帧,您可以在corotineScope中调用awaitFrame,但如果您仍然看到 Flink ,您可以设置一些固定的数字来延迟绘制阶段,如

fun Modifier.widthDependingOnTop() = composed {
    var parentY by remember { mutableFloatStateOf(Float.NaN) }

    var draw by remember {
        mutableStateOf(false)
    }

    LaunchedEffect(parentY) {
        if (parentY.isNaN().not()) {
//            delay(50)
            awaitFrame()
            draw = true
        }
    }
    onPlaced {
        parentY = it.positionInParent().y
    }
        .drawWithContent {
            if (draw) {
                drawContent()
            }
        }
        .layout { measurable, constraints ->
            val placeable = measurable.measure(
                if (parentY <= 200f) {
                    constraints.copy(maxWidth = 100)
                } else {
                    constraints
                }
            )
            layout(placeable.width, placeable.height) {
                placeable.placeRelative(x = 0, y = 0)
            }
        }
}

相关问题