resolveAdaptiveShadMenuAnchor function
ShadAnchor
resolveAdaptiveShadMenuAnchor(
- BuildContext context, {
- BuildContext? boundaryContext,
- double viewportVerticalSplit = 2 / 3,
- double gap = 8,
- double? estimatedMenuWidth,
- double? estimatedMenuHeight,
- double viewportEdgePadding = 12,
- bool centerHorizontallyInBoundary = false,
- ShadMenuHorizontalPosition horizontalPosition = ShadMenuHorizontalPosition.automatic,
- ShadMenuVerticalPosition verticalPosition = ShadMenuVerticalPosition.automatic,
Implementation
ShadAnchor resolveAdaptiveShadMenuAnchor(
BuildContext context, {
BuildContext? boundaryContext,
double viewportVerticalSplit = 2 / 3,
double gap = 8,
double? estimatedMenuWidth,
double? estimatedMenuHeight,
double viewportEdgePadding = 12,
bool centerHorizontallyInBoundary = false,
ShadMenuHorizontalPosition horizontalPosition = ShadMenuHorizontalPosition.automatic,
ShadMenuVerticalPosition verticalPosition = ShadMenuVerticalPosition.automatic,
}) {
const fallbackAnchor = ShadAnchor(childAlignment: Alignment.topLeft, overlayAlignment: Alignment.bottomLeft, offset: Offset(0, 8));
final renderBox = _safeRenderBox(context);
if (renderBox == null) {
return fallbackAnchor;
}
final overlayRenderBox = _safeRenderBox(Overlay.maybeOf(context)?.context);
final boundaryRenderBox = _safeRenderBox(boundaryContext) ?? overlayRenderBox;
try {
final viewportSize = boundaryRenderBox?.size ?? MediaQuery.sizeOf(context);
final triggerOrigin = boundaryRenderBox != null
? renderBox.localToGlobal(Offset.zero, ancestor: boundaryRenderBox)
: renderBox.localToGlobal(Offset.zero);
final triggerBottom = triggerOrigin.dy + renderBox.size.height;
final triggerRight = triggerOrigin.dx + renderBox.size.width;
final triggerCenter = triggerOrigin + Offset(renderBox.size.width / 2, renderBox.size.height / 2);
final viewportCenterX = viewportSize.width / 2;
final openDown = switch (verticalPosition) {
ShadMenuVerticalPosition.down => true,
ShadMenuVerticalPosition.up => false,
ShadMenuVerticalPosition.automatic => _shouldOpenMenuDown(
triggerOriginY: triggerOrigin.dy,
triggerBottomY: triggerBottom,
triggerCenterY: triggerCenter.dy,
viewportHeight: viewportSize.height,
viewportVerticalSplit: viewportVerticalSplit,
estimatedMenuHeight: estimatedMenuHeight,
viewportEdgePadding: viewportEdgePadding,
),
};
if (centerHorizontallyInBoundary) {
return ShadAnchor(
childAlignment: Alignment(0, openDown ? -1 : 1),
overlayAlignment: Alignment(0, openDown ? 1 : -1),
offset: Offset(viewportCenterX - triggerCenter.dx, openDown ? gap : -gap),
);
}
final alignLeft = _shouldAlignMenuLeft(
triggerOriginX: triggerOrigin.dx,
triggerRightX: triggerRight,
triggerCenterX: triggerCenter.dx,
viewportWidth: viewportSize.width,
viewportEdgePadding: viewportEdgePadding,
estimatedMenuWidth: estimatedMenuWidth,
horizontalPosition: horizontalPosition,
);
return ShadAnchor(
childAlignment: Alignment(alignLeft ? -1 : 1, openDown ? -1 : 1),
overlayAlignment: Alignment(alignLeft ? -1 : 1, openDown ? 1 : -1),
offset: Offset(0, openDown ? gap : -gap),
);
} catch (_) {
return fallbackAnchor;
}
}