我想确定
Popup
的位置。
我用androidx.compose.ui.window.Popup
像往常一样,在 Compose 中可以使用
Modifier
来做到这一点:onGloballyPositioned
但是有两个问题:
onGloballyPositioned
时,它返回零偏移量,据我了解,它将 Popup 视为根布局。弹出窗口相对于其父级定位,我可以使用父级位置、偏移量和对齐方式来计算它,也许还有其他一些(更简单的)方法来获取 Popup 全局位置?
这实际上是一个非常好的且棘手的问题,这是我最近在构建工具提示时发现的。
Popup Position 是在您传递的 PopupPositionProvider 内部计算的,或者由您传递的重载函数隐式设置的
Offset
或 Alignment
这是我从原始源代码复制的
AlignmentOffsetPositionProvider
的默认值 Popup
。
internal class AlignmentOffsetPositionProvider(
val alignment: Alignment,
val offset: IntOffset
) : PopupPositionProvider {
override fun calculatePosition(
anchorBounds: IntRect,
windowSize: IntSize,
layoutDirection: LayoutDirection,
popupContentSize: IntSize
): IntOffset {
// TODO: Decide which is the best way to round to result without reimplementing Alignment.align
var popupPosition = IntOffset(0, 0)
// Get the aligned point inside the parent
val parentAlignmentPoint = alignment.align(
IntSize.Zero,
IntSize(anchorBounds.width, anchorBounds.height),
layoutDirection
)
// Get the aligned point inside the child
val relativePopupPos = alignment.align(
IntSize.Zero,
IntSize(popupContentSize.width, popupContentSize.height),
layoutDirection
)
// Add the position of the parent
popupPosition += IntOffset(anchorBounds.left, anchorBounds.top)
// Add the distance between the parent's top left corner and the alignment point
popupPosition += parentAlignmentPoint
// Subtract the distance between the children's top left corner and the alignment point
popupPosition -= IntOffset(relativePopupPos.x, relativePopupPos.y)
// Add the user offset
val resolvedOffset = IntOffset(
offset.x * (if (layoutDirection == LayoutDirection.Ltr) 1 else -1),
offset.y
)
popupPosition += resolvedOffset
return popupPosition
}
}
您可以通过发送一个有价值的类来获得
popupPosition
。但是,当您的弹出窗口有填充时,您需要考虑到这一点,因为 popupContentSize
是内容加上填充的宽度或高度。
第二件事要注意的是,如果您的对齐方式接近任何边缘,假设开始它会返回负值,但是当 PopupProperties 具有 ClippingEnabled = true (默认值)时,它将在屏幕上重置为零。您也应该考虑到这一点。
我有一些 Popup 示例,您可以在此处检查并查看仓位和其他属性的日志。