diff --git a/src/CommunityToolkit.Maui.Core/Handlers/Popup/PopUpHandler.windows.cs b/src/CommunityToolkit.Maui.Core/Handlers/Popup/PopUpHandler.windows.cs index f369daf75..0c3e24321 100644 --- a/src/CommunityToolkit.Maui.Core/Handlers/Popup/PopUpHandler.windows.cs +++ b/src/CommunityToolkit.Maui.Core/Handlers/Popup/PopUpHandler.windows.cs @@ -1,6 +1,7 @@ using CommunityToolkit.Maui.Core.Views; using Microsoft.Maui.Handlers; using Microsoft.Maui.Platform; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; @@ -88,7 +89,7 @@ public static void MapColor(PopupHandler handler, IPopup view) /// An instance of . public static void MapSize(PopupHandler handler, IPopup view) { - handler.PlatformView.SetSize(view); + handler.PlatformView.SetSize(view, handler.MauiContext); } /// @@ -100,6 +101,10 @@ protected override void DisconnectHandler(Popup platformView) parent.IsHitTestVisible = true; platformView.IsOpen = false; platformView.Closed -= OnClosed; + if (MauiContext is not null) + { + MauiContext.GetPlatformWindow().SizeChanged -= OnSizeChanged; + } } /// @@ -114,6 +119,10 @@ protected override void ConnectHandler(Popup platformView) { platformView.Closed += OnClosed; platformView.ConfigureControl(VirtualView, MauiContext); + if (MauiContext is not null) + { + MauiContext.GetPlatformWindow().SizeChanged += OnSizeChanged; + } base.ConnectHandler(platformView); } @@ -124,4 +133,13 @@ void OnClosed(object? sender, object e) VirtualView.Handler?.Invoke(nameof(IPopup.OnDismissedByTappingOutsideOfPopup)); } } + + void OnSizeChanged(object? sender, WindowSizeChangedEventArgs e) + { + if (VirtualView is not null) + { + PopupExtensions.SetSize(PlatformView, VirtualView, MauiContext); + PopupExtensions.SetLayout(PlatformView, VirtualView, MauiContext); + } + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Maui.Core/Views/Popup/PopupExtensions.windows.cs b/src/CommunityToolkit.Maui.Core/Views/Popup/PopupExtensions.windows.cs index 7a63639d6..cb9cbbbaa 100644 --- a/src/CommunityToolkit.Maui.Core/Views/Popup/PopupExtensions.windows.cs +++ b/src/CommunityToolkit.Maui.Core/Views/Popup/PopupExtensions.windows.cs @@ -54,7 +54,7 @@ public static void ConfigureControl(this Popup mauiPopup, IPopup popup, IMauiCon mauiPopup.Child = handler.VirtualView.Content?.ToPlatform(mauiContext); } - mauiPopup.SetSize(popup); + mauiPopup.SetSize(popup, mauiContext); mauiPopup.SetLayout(popup, mauiContext); } @@ -63,41 +63,58 @@ public static void ConfigureControl(this Popup mauiPopup, IPopup popup, IMauiCon /// /// An instance of . /// An instance of . - public static void SetSize(this Popup mauiPopup, IPopup popup) + /// An instance of . + public static void SetSize(this Popup mauiPopup, IPopup popup, IMauiContext? mauiContext) { + ArgumentNullException.ThrowIfNull(mauiContext); + ArgumentNullException.ThrowIfNull(popup.Content); + const double defaultBorderThickness = 0; const double defaultSize = 600; - var standardSize = new Size { Width = defaultSize, Height = defaultSize / 2 }; + var popupParent = mauiContext.GetPlatformWindow(); + var currentSize = new Size { Width = defaultSize, Height = defaultSize / 2 }; - var currentSize = popup.Size != default ? popup.Size : standardSize; - - if (popup.Content is not null && popup.Size == default) + if (popup.Size.IsZero) { - var content = popup.Content; - // There are some situations when the Width and Height values will be NaN - // normally when the dev doesn't set the HeightRequest and WidthRequest - // and we can't use comparison on those, so the only to prevent the application to crash - // is using this try/catch - try + if (double.IsNaN(popup.Content.Width) || (double.IsNaN(popup.Content.Height))) { - currentSize = new Size(content.Width, content.Height); + currentSize = popup.Content.Measure(popupParent.Bounds.Width, popupParent.Bounds.Height); + + if (double.IsNaN(popup.Content.Width)) + { + currentSize.Width = popup.HorizontalOptions == LayoutAlignment.Fill ? popupParent.Bounds.Width : currentSize.Width; + } + if (double.IsNaN(popup.Content.Height)) + { + currentSize.Height = popup.VerticalOptions == LayoutAlignment.Fill ? popupParent.Bounds.Height : currentSize.Height; + } } - catch (ArgumentException) + else { + currentSize.Width = popup.Content.Width; + currentSize.Height = popup.Content.Height; } } - - if (popup.Parent is IView popupParent) + else { - currentSize.Width = Math.Min(currentSize.Width, popupParent.Frame.Width); - currentSize.Height = Math.Min(currentSize.Height, popupParent.Frame.Height); + currentSize.Width = popup.Size.Width; + currentSize.Height = popup.Size.Height; } + currentSize.Width = Math.Min(currentSize.Width, popupParent.Bounds.Width); + currentSize.Height = Math.Min(currentSize.Height, popupParent.Bounds.Height); + mauiPopup.Width = currentSize.Width; mauiPopup.Height = currentSize.Height; mauiPopup.MinWidth = mauiPopup.MaxWidth = currentSize.Width + (defaultBorderThickness * 2); mauiPopup.MinHeight = mauiPopup.MaxHeight = currentSize.Height + (defaultBorderThickness * 2); + + if (mauiPopup.Child is FrameworkElement control) + { + control.Width = mauiPopup.Width; + control.Height = mauiPopup.Height; + } } /// @@ -109,10 +126,12 @@ public static void SetSize(this Popup mauiPopup, IPopup popup) public static void SetLayout(this Popup mauiPopup, IPopup popup, IMauiContext? mauiContext) { ArgumentNullException.ThrowIfNull(mauiContext); - var popupParent = popup.Parent as IView; - popup.Content?.Measure(double.PositiveInfinity, double.PositiveInfinity); - var contentSize = popup.Content?.ToPlatform(mauiContext).DesiredSize ?? Windows.Foundation.Size.Empty; - var popupParentFrame = popupParent?.Frame ?? new Rect(0, 0, contentSize.Width, contentSize.Height); + ArgumentNullException.ThrowIfNull(popup.Content); + + var popupParent = mauiContext.GetPlatformWindow(); + popup.Content.Measure(double.PositiveInfinity, double.PositiveInfinity); + var contentSize = popup.Content.ToPlatform(mauiContext).DesiredSize; + var popupParentFrame = popupParent.Bounds; var verticalOptions = popup.VerticalOptions; var horizontalOptions = popup.HorizontalOptions; @@ -144,19 +163,19 @@ public static void SetLayout(this Popup mauiPopup, IPopup popup, IMauiContext? m { mauiPopup.DesiredPlacement = PopupPlacementMode.BottomEdgeAlignedRight; mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width); - mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2; + mauiPopup.VerticalOffset = popupParentFrame.Height - contentSize.Height; } else if (IsBottom(verticalOptions, horizontalOptions)) { mauiPopup.DesiredPlacement = PopupPlacementMode.Bottom; mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; - mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2; + mauiPopup.VerticalOffset = popupParentFrame.Height - contentSize.Height; } else if (IsBottomLeft(verticalOptions, horizontalOptions)) { mauiPopup.DesiredPlacement = PopupPlacementMode.BottomEdgeAlignedLeft; mauiPopup.HorizontalOffset = 0; - mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2; + mauiPopup.VerticalOffset = popupParentFrame.Height - contentSize.Height; } else if (IsLeft(verticalOptions, horizontalOptions)) { @@ -164,6 +183,54 @@ public static void SetLayout(this Popup mauiPopup, IPopup popup, IMauiContext? m mauiPopup.HorizontalOffset = 0; mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; } + else if (IsCenter(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } + else if (IsFillLeft(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = 0; + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } + else if (IsFillCenter(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } + else if (IsFillRight(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width); + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } + else if (IsTopFill(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = 0; + } + else if (IsCenterFill(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } + else if (IsBottomFill(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = popupParentFrame.Height - contentSize.Height; + } + else if (IsFill(verticalOptions, horizontalOptions)) + { + mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; + mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2; + mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2; + } else if (popup.Anchor is null) { mauiPopup.DesiredPlacement = PopupPlacementMode.Auto; @@ -183,5 +250,13 @@ public static void SetLayout(this Popup mauiPopup, IPopup popup, IMauiContext? m static bool IsBottom(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Center; static bool IsBottomLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Start; static bool IsLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.Start; + static bool IsCenter(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.Center; + static bool IsFillLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Fill && horizontalOptions == LayoutAlignment.Start; + static bool IsFillCenter(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Fill && horizontalOptions == LayoutAlignment.Center; + static bool IsFillRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Fill && horizontalOptions == LayoutAlignment.End; + static bool IsTopFill(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.Fill; + static bool IsCenterFill(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.Fill; + static bool IsBottomFill(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Fill; + static bool IsFill(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Fill && horizontalOptions == LayoutAlignment.Fill; } } \ No newline at end of file