Skip to content

Instantly share code, notes, and snippets.

@KlassenKonstantin
Created May 21, 2023 10:36
Show Gist options
  • Save KlassenKonstantin/b1661dc3f6a6bd49381568dc9ab7a298 to your computer and use it in GitHub Desktop.
Save KlassenKonstantin/b1661dc3f6a6bd49381568dc9ab7a298 to your computer and use it in GitHub Desktop.
PlacementWithinAnchor
@Composable
fun PlacementWithinAnchor(
modifier: Modifier,
content: @Composable PlacementWithinAnchorScope.() -> Unit
) {
CompositionLocalProvider(
LocalLayoutCoordinatesHolder provides ContainerLayoutCoordinatesHolder()
) {
Box(
modifier = modifier
) {
PlacementWithinAnchorScope.content()
}
}
}
private val LocalLayoutCoordinatesHolder = compositionLocalOf<ContainerLayoutCoordinatesHolder> {
throw IllegalStateException("No LayoutCoordinates provided")
}
object PlacementWithinAnchorScope {
@Stable
fun Modifier.placementAnchor() = composed {
val currentLayoutCoordinatesHolder = LocalLayoutCoordinatesHolder.current
onPlaced {
currentLayoutCoordinatesHolder.containerLayoutCoordinates = it
}
}
@Stable
fun Modifier.onPlacedWithinAnchor(
onPlaced: (WithinAnchor) -> Unit
) = composed {
val currentLocalLayoutCoordinatesHolder = LocalLayoutCoordinatesHolder.current
onGloballyPositioned {
val anchorLayoutCoordinates = currentLocalLayoutCoordinatesHolder.containerLayoutCoordinates
val boundsWithinAnchor = anchorLayoutCoordinates
.localBoundingBoxOf(it, false)
val positionWithinAnchor = Offset(
boundsWithinAnchor.left,
boundsWithinAnchor.top
)
val corners = with(boundsWithinAnchor) { listOf(topLeft, topRight, bottomLeft, bottomRight) }
val anchorBounds = Rect(Offset.Zero, anchorLayoutCoordinates.size.toSize())
val isVisible = corners.any { anchorBounds.contains(it) }
onPlaced(WithinAnchor(positionWithinAnchor, boundsWithinAnchor, isVisible))
}
}
}
@Immutable
data class WithinAnchor(
val position: Offset = Offset.Zero,
val bounds: Rect = Rect.Zero,
val isVisible: Boolean = false
)
class ContainerLayoutCoordinatesHolder {
lateinit var containerLayoutCoordinates: LayoutCoordinates
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment