如何获取 Compose 中 Popup 的全局位置?

问题描述 投票:0回答:1

我想确定

Popup
的位置。 我用
androidx.compose.ui.window.Popup

像往常一样,在 Compose 中可以使用

Modifier
来做到这一点:
onGloballyPositioned

但是有两个问题:

  1. Popup 没有修饰符作为参数。
  2. 当我尝试在子视图中使用
    onGloballyPositioned
    时,它返回零偏移量,据我了解,它将 Popup 视为根布局。

弹出窗口相对于其父级定位,我可以使用父级位置、偏移量和对齐方式来计算它,也许还有其他一些(更简单的)方法来获取 Popup 全局位置?

android android-jetpack-compose popup android-window
1个回答
0
投票

这实际上是一个非常好的且棘手的问题,这是我最近在构建工具提示时发现的。

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 示例,您可以在此处检查并查看仓位和其他属性的日志。

https://github.com/SmartToolFactory/Jetpack-Compose-Tutorials/blob/d23c6fcdd0da2393335dc2234cea17e3cb0895e8/Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter3_layout/Tutorial3_11Popup1.kt #L472

© www.soinside.com 2019 - 2024. All rights reserved.