Last active
June 27, 2024 15:09
-
-
Save habibg1232191/2ca21b6f113a875e05f4494f32f87d4e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.animation.* | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.layout.Layout | |
import androidx.compose.ui.unit.IntOffset | |
import androidx.compose.ui.window.Popup | |
@Composable | |
fun AniJinPopup( | |
expanded: Boolean, | |
popupPositionProvider: PopupPositionProvider, | |
onDismissRequest: (() -> Unit)? = null, | |
onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false }, | |
onKeyEvent: ((KeyEvent) -> Boolean) = { false }, | |
focusable: Boolean = false, | |
enter: EnterTransition = fadeIn(), | |
exit: ExitTransition = fadeOut(), | |
modifier: Modifier = Modifier, | |
content: @Composable AnimatedVisibilityScope.() -> Unit | |
) { | |
val expandedState = remember { MutableTransitionState(false) } | |
expandedState.targetState = expanded | |
if(expandedState.currentState || expandedState.targetState || !expandedState.isIdle) { | |
Popup( | |
focusable = focusable, | |
popupPositionProvider = popupPositionProvider, | |
onDismissRequest = onDismissRequest, | |
onPreviewKeyEvent = onPreviewKeyEvent, | |
onKeyEvent = onKeyEvent | |
) { | |
AnimatedVisibility( | |
visibleState = expandedState, | |
enter = enter, | |
exit = exit, | |
modifier = modifier, | |
content = content | |
) | |
} | |
} | |
} | |
@Composable | |
fun AniJinPopup( | |
expanded: Boolean, | |
alignment: Alignment = Alignment.TopStart, | |
offset: IntOffset = IntOffset(0, 0), | |
onDismissRequest: (() -> Unit)? = null, | |
onPreviewKeyEvent: ((KeyEvent) -> Boolean) = { false }, | |
onKeyEvent: ((KeyEvent) -> Boolean) = { false }, | |
focusable: Boolean = false, | |
enter: EnterTransition = fadeIn(), | |
exit: ExitTransition = fadeOut(), | |
modifier: Modifier = Modifier, | |
content: @Composable AnimatedVisibilityScope.() -> Unit | |
) { | |
val popupPositionProvider = remember(alignment, offset) { | |
AlignmentOffsetPositionProvider( | |
alignment, | |
offset | |
) | |
} | |
AniJinPopup( | |
expanded = expanded, | |
popupPositionProvider = popupPositionProvider, | |
onDismissRequest = onDismissRequest, | |
onPreviewKeyEvent = onPreviewKeyEvent, | |
onKeyEvent = onKeyEvent, | |
focusable = focusable, | |
enter = enter, | |
exit = exit, | |
modifier = modifier, | |
content = content | |
) | |
} | |
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment