@Composable
fun OnGloballyPositionedExample() {
// Get local density from composable
val localDensity = LocalDensity.current
// Create element height in pixel state
var columnHeightPx by remember {
mutableStateOf(0f)
}
// Create element height in dp state
var columnHeightDp by remember {
mutableStateOf(0.dp)
}
Column(
modifier = Modifier
.onGloballyPositioned { coordinates ->
// Set column height using the LayoutCoordinates
columnHeightPx = coordinates.size.height.toFloat()
columnHeightDp = with(localDensity) { coordinates.size.height.toDp() }
}
) {
Text(text = "Column height in pixel: $columnHeightPx")
Text(text = "Column height in dp: $columnHeightDp")
}
}
@Composable
fun GetHeightCompose() {
// get local density from composable
val localDensity = LocalDensity.current
var heightIs by remember {
mutableStateOf(0.dp)
}
Box(modifier = Modifier.fillMaxSize()) {
// Important column should not be inside a Surface in order to be measured correctly
Column(
Modifier
.onGloballyPositioned { coordinates ->
heightIs = with(localDensity) { coordinates.size.height.toDp() }
}) {
Text(text = "If you want to know the height of this column with text and button in Dp it is: $heightIs")
Button(onClick = { /*TODO*/ }) {
Text(text = "Random Button")
}
}
}
}
**
* SubcomposeLayout that [SubcomposeMeasureScope.subcompose]s [mainContent]
* and gets total size of [mainContent] and passes this size to [dependentContent].
* This layout passes exact size of content unlike
* BoxWithConstraints which returns [Constraints] that doesn't match Composable dimensions under
* some circumstances
*
* @param placeMainContent when set to true places main content. Set this flag to false
* when dimensions of content is required for inside [mainContent]. Just measure it then pass
* its dimensions to any child composable
*
* @param mainContent Composable is used for calculating size and pass it
* to Composables that depend on it
*
* @param dependentContent Composable requires dimensions of [mainContent] to set its size.
* One example for this is overlay over Composable that should match [mainContent] size.
*
*/
@Composable
fun DimensionSubcomposeLayout(
modifier: Modifier = Modifier,
placeMainContent: Boolean = true,
mainContent: @Composable () -> Unit,
dependentContent: @Composable (Size) -> Unit
) {
SubcomposeLayout(
modifier = modifier
) { constraints: Constraints ->
// Subcompose(compose only a section) main content and get Placeable
val mainPlaceables: List<Placeable> = subcompose(SlotsEnum.Main, mainContent)
.map {
it.measure(constraints.copy(minWidth = 0, minHeight = 0))
}
// Get max width and height of main component
var maxWidth = 0
var maxHeight = 0
mainPlaceables.forEach { placeable: Placeable ->
maxWidth += placeable.width
maxHeight = placeable.height
}
val dependentPlaceables: List<Placeable> = subcompose(SlotsEnum.Dependent) {
dependentContent(Size(maxWidth.toFloat(), maxHeight.toFloat()))
}
.map { measurable: Measurable ->
measurable.measure(constraints)
}
layout(maxWidth, maxHeight) {
if (placeMainContent) {
mainPlaceables.forEach { placeable: Placeable ->
placeable.placeRelative(0, 0)
}
}
dependentPlaceables.forEach { placeable: Placeable ->
placeable.placeRelative(0, 0)
}
}
}
}
enum class SlotsEnum { Main, Dependent }
5条答案
按热度按时间r6vfmomb1#
如果您想在合成后获得按钮的高度,则可以使用:onGloballyPositionedModifier.
它返回一个LayoutCoordinates对象,该对象包含按钮的大小。
使用
onGloballyPositioned
修饰符的示例:ctzwtxfj2#
完整的解决方案如下:
ddarikpa3#
您也可以使用
BoxWithConstraints
,如下所示:但我不确定它是否适合你的特定用途。
5gfr0r5j4#
使用
Modifier.onSizeChanged{}
或Modifier.globallyPositioned{}
可能会导致无限的重组,如果你不小心,在OP的问题时,一个组合的大小影响另一个。已更改大小(kotlin.Function1)
使用MutableState中的onSizeChanged大小值更新布局会导致读取新的大小值并在后续帧中重新组合布局,从而导致一帧滞后。
您可以使用onSizeChanged来影响绘制操作。使用Layout或SubcomposeLayout使一个组件的大小能够影响另一个组件的大小。
即使可以绘制,如果帧的变化是明显的用户,它不会看起来很好
比如说
文本的背景在下一次重新组合时从覆盖其边界的初始背景移动到200.dp大小。如果您正在执行将任何UI绘图从一个维度更改为另一个维度的操作,则可能会看起来像闪光或故障。
获取元素高度而不进行重新组合的第一种方法是使用
BoxWithConstraints
BoxWithConstraints
'BoxScope
包含dp中的maxHeight
和整数中的constraints.maxHeigh
t。但是,BoxWithConstraints在某些情况下返回大小不精确的约束,如使用Modifier. fillMaxHeight、没有任何大小修饰符或具有垂直滚动的父级返回不正确的值
您可以检出从BoxWithConstraints返回的尺寸的this answer,Constraints部分显示了使用BoxWithConstraints将获得的内容。
verticalScroll返回约束。无限高。
获取精确大小的可靠方法是使用SubcomposeLayout
如何获得准确的大小没有重组?
用途
或
vlurs2pr5#
我设法实现了一个变通方法,通过使从
Modifier.onSizeChanged
读取的组合现在无状态,来减少(不是完全消除)重新组合的次数,这不是最好的方法,但它完成了工作。