Skip to content

Commit

Permalink
Fix placement of popup when anchor is zero-sized
Browse files Browse the repository at this point in the history
  • Loading branch information
saket committed Jan 23, 2023
1 parent eead205 commit 464db26
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 11 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,38 @@ internal class CascadePopupTest {
}
}

@Test fun zero_sized_anchor() {
composeTestRule.setContent {
CascadeMaterialTheme {
Box(
Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(10.dp))
) {
// This anchor has a non-zero size, but its internal
// padding does not leave any space for content.
Box(
Modifier
.size(10.dp)
.align(Alignment.TopEnd)
.padding(5.dp)
) {
CascadeDropdownMenu(
expanded = true,
onDismissRequest = {}
) {
DropdownMenuItem(
text = { Text("Batman Ipsum") },
onClick = {}
)
}
}
}
}
}
dropshots.assertDeviceSnapshot()
}

@Composable
private fun PopupScaffold(
align: Alignment = Alignment.TopStart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.boundsInWindow
import androidx.compose.ui.layout.findRootCoordinates
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.unit.toSize

@Immutable
internal data class ScreenRelativeBounds(
Expand All @@ -29,18 +31,19 @@ internal data class RootLayoutCoordinatesInfo(
}

internal fun ScreenRelativeBounds(coordinates: LayoutCoordinates, owner: View): ScreenRelativeBounds {
return coordinates.findRootCoordinates().let { rootCoordinates ->
ScreenRelativeBounds(
boundsInRoot = rootCoordinates.localBoundingBoxOf(coordinates),
root = RootLayoutCoordinatesInfo(
layoutBoundsInWindow = rootCoordinates.boundsInWindow(),
windowPositionOnScreen = run {
owner.rootView.getLocationOnScreen(intArrayBuffer)
Offset(x = intArrayBuffer[0].toFloat(), y = intArrayBuffer[1].toFloat())
}
)
return ScreenRelativeBounds(
boundsInRoot = Rect(
offset = coordinates.positionInRoot(),
size = coordinates.size.toSize()
),
root = RootLayoutCoordinatesInfo(
layoutBoundsInWindow = coordinates.findRootCoordinates().boundsInWindow(),
windowPositionOnScreen = run {
owner.rootView.getLocationOnScreen(intArrayBuffer)
Offset(x = intArrayBuffer[0].toFloat(), y = intArrayBuffer[1].toFloat())
}
)
}
)
}

// I do not expect this to be shared across threads to need any synchronization.
Expand Down

0 comments on commit 464db26

Please sign in to comment.