@@ -75,53 +75,66 @@ fun ListPopup(
7575) {
7676 if (! show.value) return
7777
78- val currentOnDismissRequest by rememberUpdatedState(onDismissRequest)
79- val currentContent by rememberUpdatedState(content)
80-
81- var offset by remember { mutableStateOf(IntOffset .Zero ) }
8278 val density = LocalDensity .current
8379 val layoutDirection = LocalLayoutDirection .current
8480
8581 val getWindowSizeState = rememberUpdatedState(getWindowSize())
8682 var windowSize by remember { mutableStateOf(IntSize (getWindowSizeState.value.width, getWindowSizeState.value.height)) }
8783 var parentBounds by remember { mutableStateOf(IntRect .Zero ) }
8884
89- val windowBounds = with (density) {
90- IntRect (
91- left = WindowInsets .displayCutout.asPaddingValues(density).calculateLeftPadding(layoutDirection).roundToPx(),
92- top = WindowInsets .statusBars.asPaddingValues().calculateTopPadding().roundToPx(),
93- right = windowSize.width -
94- WindowInsets .displayCutout.asPaddingValues(density).calculateRightPadding(layoutDirection).roundToPx(),
95- bottom = windowSize.height -
96- WindowInsets .navigationBars.asPaddingValues().calculateBottomPadding().roundToPx() -
97- WindowInsets .captionBar.asPaddingValues().calculateBottomPadding().roundToPx()
98- )
99- }
100-
101- var popupContentSize by remember { mutableStateOf(IntSize .Zero ) }
85+ Layout (
86+ modifier = Modifier .onGloballyPositioned { childCoordinates ->
87+ childCoordinates.parentLayoutCoordinates?.let { parentLayoutCoordinates ->
88+ val positionInWindow = parentLayoutCoordinates.positionInWindow()
89+ val newParentBounds = IntRect (
90+ left = positionInWindow.x.toInt(),
91+ top = positionInWindow.y.toInt(),
92+ right = positionInWindow.x.toInt() + parentLayoutCoordinates.size.width,
93+ bottom = positionInWindow.y.toInt() + parentLayoutCoordinates.size.height
94+ )
95+ if (parentBounds != newParentBounds) parentBounds = newParentBounds
96+ }
97+ val newUtilWindowSize = getWindowSizeState.value
98+ val newIntSize = IntSize (newUtilWindowSize.width, newUtilWindowSize.height)
99+ if (windowSize != newIntSize) windowSize = newIntSize
100+ }
101+ ) { _, _ -> layout(0 , 0 ) {} }
102102
103- val popupMargin = remember(popupPositionProvider, density, layoutDirection ) {
104- val popupMarginsPd = popupPositionProvider.getMargins()
103+ val popupMargin = remember(popupPositionProvider, layoutDirection, density ) {
104+ val pd = popupPositionProvider.getMargins()
105105 with (density) {
106106 IntRect (
107- left = popupMarginsPd .calculateLeftPadding(layoutDirection).roundToPx(),
108- top = popupMarginsPd .calculateTopPadding().roundToPx(),
109- right = popupMarginsPd .calculateRightPadding(layoutDirection).roundToPx(),
110- bottom = popupMarginsPd .calculateBottomPadding().roundToPx()
107+ left = pd .calculateLeftPadding(layoutDirection).roundToPx(),
108+ top = pd .calculateTopPadding().roundToPx(),
109+ right = pd .calculateRightPadding(layoutDirection).roundToPx(),
110+ bottom = pd .calculateBottomPadding().roundToPx()
111111 )
112112 }
113113 }
114114
115- val transformOrigin = remember(parentBounds, popupMargin, windowSize, density, alignment) {
116- val xInWindow = if (alignment in listOf (
117- PopupPositionProvider .Align .Right ,
118- PopupPositionProvider .Align .TopRight ,
119- PopupPositionProvider .Align .BottomRight ,
120- )
121- ) {
122- parentBounds.right - popupMargin.right - with (density) { 64 .dp.roundToPx() }
123- } else {
124- parentBounds.left + popupMargin.left + with (density) { 64 .dp.roundToPx() }
115+ val displayCutoutPadding = WindowInsets .displayCutout.asPaddingValues(density)
116+ val statusBarsPadding = WindowInsets .statusBars.asPaddingValues()
117+ val navigationBarsPadding = WindowInsets .navigationBars.asPaddingValues()
118+ val captionBarPadding = WindowInsets .captionBar.asPaddingValues()
119+
120+ val windowBounds = with (density) {
121+ IntRect (
122+ left = displayCutoutPadding.calculateLeftPadding(layoutDirection).roundToPx(),
123+ top = statusBarsPadding.calculateTopPadding().roundToPx(),
124+ right = windowSize.width - displayCutoutPadding.calculateRightPadding(layoutDirection).roundToPx(),
125+ bottom = windowSize.height -
126+ navigationBarsPadding.calculateBottomPadding().roundToPx() -
127+ captionBarPadding.calculateBottomPadding().roundToPx()
128+ )
129+ }
130+
131+ val transformOrigin = remember(parentBounds, popupMargin, windowSize, alignment, density) {
132+ val xInWindow = when (alignment) {
133+ PopupPositionProvider .Align .Right ,
134+ PopupPositionProvider .Align .TopRight ,
135+ PopupPositionProvider .Align .BottomRight -> parentBounds.right - popupMargin.right - with (density) { 64 .dp.roundToPx() }
136+
137+ else -> parentBounds.left + popupMargin.left + with (density) { 64 .dp.roundToPx() }
125138 }
126139 val yInWindow = parentBounds.top + parentBounds.height / 2 - with (density) { 56 .dp.roundToPx() }
127140 safeTransformOrigin(
@@ -130,96 +143,78 @@ fun ListPopup(
130143 )
131144 }
132145
133- // Anchor point for the popup
134- Layout (
135- modifier = Modifier .onGloballyPositioned { childCoordinates ->
136- val parentLayoutCoordinates = childCoordinates.parentLayoutCoordinates
137- if (parentLayoutCoordinates != null ) {
138- val positionInWindow = parentLayoutCoordinates.positionInWindow()
139- parentBounds = IntRect (
140- left = positionInWindow.x.toInt(),
141- top = positionInWindow.y.toInt(),
142- right = positionInWindow.x.toInt() + parentLayoutCoordinates.size.width,
143- bottom = positionInWindow.y.toInt() + parentLayoutCoordinates.size.height
144- )
145- }
146- val newUtilWindowSize = getWindowSizeState.value
147- val newIntSize = IntSize (newUtilWindowSize.width, newUtilWindowSize.height)
148- if (windowSize != newIntSize) {
149- windowSize = newIntSize
150- }
151- }
152- ) { _, _ ->
153- layout(0 , 0 ) {}
154- }
146+ var offset by remember { mutableStateOf(IntOffset .Zero ) }
147+ var popupContentSize by remember { mutableStateOf(IntSize .Zero ) }
155148
156- PopupLayout (
157- visible = show,
158- enableWindowDim = enableWindowDim,
159- transformOrigin = { transformOrigin },
160- ) {
161- val shape = remember { SmoothRoundedCornerShape (16 .dp) }
162- val elevationPx = with (density) { shadowElevation.toPx() }
163-
164- Box (
165- modifier = popupModifier
166- .pointerInput(currentOnDismissRequest) {
167- detectTapGestures {
168- currentOnDismissRequest?.invoke()
169- }
170- }
171- .layout { measurable, constraints ->
172- val placeable = measurable.measure(
173- constraints.copy(
174- minWidth = if (minWidth.roundToPx() <= windowSize.width) minWidth.roundToPx() else windowSize.width,
175- minHeight = if (50 .dp.roundToPx() <= windowSize.height) 50 .dp.roundToPx() else windowSize.height,
176- maxHeight = maxHeight?.roundToPx()?.coerceAtLeast(50 .dp.roundToPx())
177- ? : (windowBounds.height - popupMargin.top - popupMargin.bottom).coerceAtLeast(
178- 50 .dp.roundToPx()
179- ),
180- maxWidth = if (minWidth.roundToPx() <= windowSize.width) windowSize.width else minWidth.roundToPx()
181- )
182- )
183- val measuredSize = IntSize (placeable.width, placeable.height)
184- if (popupContentSize != measuredSize) {
185- popupContentSize = measuredSize
186- }
149+ if (parentBounds != IntRect .Zero && windowSize != IntSize .Zero ) {
150+ PopupLayout (
151+ visible = show,
152+ enableWindowDim = enableWindowDim,
153+ transformOrigin = { transformOrigin },
154+ ) {
155+ val shape = remember { SmoothRoundedCornerShape (16 .dp) }
156+ val elevationPx = with (density) { shadowElevation.toPx() }
187157
188- val calculatedOffset = popupPositionProvider.calculatePosition(
189- parentBounds,
190- windowBounds,
191- layoutDirection,
192- measuredSize,
193- popupMargin,
194- alignment
195- )
196- if (offset != calculatedOffset) {
197- offset = calculatedOffset
158+ Box (
159+ modifier = popupModifier
160+ .pointerInput(onDismissRequest) {
161+ detectTapGestures(
162+ onTap = { onDismissRequest?.invoke() }
163+ )
198164 }
165+ .layout { measurable, constraints ->
166+ val placeable = measurable.measure(
167+ constraints.copy(
168+ minWidth = if (minWidth.roundToPx() <= windowSize.width) minWidth.roundToPx() else windowSize.width,
169+ minHeight = if (50 .dp.roundToPx() <= windowSize.height) 50 .dp.roundToPx() else windowSize.height,
170+ maxHeight = maxHeight?.roundToPx()?.coerceAtLeast(50 .dp.roundToPx())
171+ ? : (windowBounds.height - popupMargin.top - popupMargin.bottom).coerceAtLeast(
172+ 50 .dp.roundToPx()
173+ ),
174+ maxWidth = if (minWidth.roundToPx() <= windowSize.width) windowSize.width else minWidth.roundToPx()
175+ )
176+ )
177+ val measuredSize = IntSize (placeable.width, placeable.height)
178+ if (popupContentSize != measuredSize) {
179+ popupContentSize = measuredSize
180+ }
181+
182+ val calculatedOffset = popupPositionProvider.calculatePosition(
183+ parentBounds,
184+ windowBounds,
185+ layoutDirection,
186+ measuredSize,
187+ popupMargin,
188+ alignment
189+ )
190+ if (offset != calculatedOffset) {
191+ offset = calculatedOffset
192+ }
199193
200- layout(constraints.maxWidth, constraints.maxHeight) {
201- placeable.place(offset)
194+ layout(constraints.maxWidth, constraints.maxHeight) {
195+ placeable.place(offset)
196+ }
202197 }
203- }
204- ) {
205- Box (
206- modifier = Modifier
207- .graphicsLayer(
208- clip = true ,
209- shape = shape,
210- shadowElevation = elevationPx,
211- ambientShadowColor = MiuixTheme .colorScheme.windowDimming,
212- spotShadowColor = MiuixTheme .colorScheme.windowDimming
213- )
214- .background(MiuixTheme .colorScheme.surface)
215198 ) {
216- currentContent()
199+ Box (
200+ modifier = Modifier
201+ .graphicsLayer(
202+ clip = true ,
203+ shape = shape,
204+ shadowElevation = elevationPx,
205+ ambientShadowColor = MiuixTheme .colorScheme.windowDimming,
206+ spotShadowColor = MiuixTheme .colorScheme.windowDimming
207+ )
208+ .background(MiuixTheme .colorScheme.surface)
209+ ) {
210+ content()
211+ }
217212 }
218213 }
219214 }
220215
221216 BackHandler (enabled = show.value) {
222- currentOnDismissRequest ?.invoke()
217+ onDismissRequest ?.invoke()
223218 }
224219}
225220
0 commit comments