Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Popup size on Android and iOS #1361

Merged
merged 32 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
08324a5
Fix Popup size on Android
cat0363 Aug 21, 2023
a457e44
Fix Popup size on Android
cat0363 Aug 21, 2023
1ef271e
Fix Popup size on Android
cat0363 Aug 22, 2023
96d1357
Merge branch 'main' into Issue-1353
cat0363 Aug 22, 2023
93ab63d
Fix Popup size on Android and iOS
cat0363 Aug 23, 2023
f722969
Merge branch 'Issue-1353' of https://github.com/cat0363/Maui into Iss…
cat0363 Aug 23, 2023
6fec5e9
Invert if
cat0363 Aug 24, 2023
f0c293c
Merge branch 'main' into Issue-1353
cat0363 Aug 25, 2023
e0b77c6
Merge branch 'main' into Issue-1353
brminnick Aug 27, 2023
16511a1
Merge branch 'main' into Issue-1353
brminnick Aug 27, 2023
efb76a6
Change local variable to static variable
cat0363 Aug 28, 2023
680a270
Merge branch 'main' into Issue-1353
cat0363 Aug 28, 2023
a1e07b3
Merge branch 'main' into Issue-1353
cat0363 Aug 30, 2023
13ef408
Fix popup position and closing
cat0363 Aug 31, 2023
b6aec4c
Merge branch 'main' into Issue-1353
cat0363 Sep 7, 2023
8959f6f
Merge branch 'main' into Issue-1353
brminnick Sep 7, 2023
ddef95e
Merge branch 'main' into Issue-1353
cat0363 Sep 7, 2023
7200e2c
Merge branch 'main' into Issue-1353
cat0363 Sep 8, 2023
a2a7dca
Merge branch 'main' into Issue-1353
brminnick Sep 9, 2023
385111a
Use pattern matching
brminnick Sep 9, 2023
4cd5eed
Merge branch 'Issue-1353' of https://github.com/cat0363/Maui into pr/…
brminnick Sep 9, 2023
cd2ad14
Merge branch 'main' into Issue-1353
cat0363 Sep 14, 2023
21da66d
Merge branch 'main' into Issue-1353
brminnick Sep 23, 2023
a9ca863
Change rootViewController
cat0363 Sep 24, 2023
71402bb
Add CustomSizeAndPositionPopupPage
brminnick Sep 25, 2023
f5b66ec
Update CustomSizeAndPositionPopupPage.xaml
brminnick Sep 25, 2023
4c345fa
Update CustomSizeAndPositionPopupPage.xaml
brminnick Sep 25, 2023
711b20f
Fixed MacCatalyst Popup position
cat0363 Sep 26, 2023
3c2ceb7
Fixed MacCatalyst Popup size
cat0363 Sep 26, 2023
a91693c
Fix MacCatalyst Popup margin
cat0363 Sep 27, 2023
ec7dac0
Fix Android popup size
cat0363 Sep 27, 2023
dcb60bb
Update Formatting
brminnick Sep 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 82 additions & 81 deletions src/CommunityToolkit.Maui.Core/Views/Popup/PopupExtensions.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Android.Views;
using Microsoft.Maui.Platform;
using AColorRes = Android.Resource.Color;
using AInsets = Android.Graphics.Insets;
using APoint = Android.Graphics.Point;
using ARect = Android.Graphics.Rect;
using AView = Android.Views.View;
Expand All @@ -17,6 +16,10 @@ namespace CommunityToolkit.Maui.Core.Views;
/// </summary>
public static class PopupExtensions
{
static APoint realSize = new();
static APoint displaySize = new();
static ARect contentRect = new();

/// <summary>
/// Method to update the <see cref="IPopup.Anchor"/> view.
/// </summary>
Expand Down Expand Up @@ -114,79 +117,18 @@ public static void SetSize(this Dialog dialog, in IPopup popup, in AView contain
realContentWidth = 0,
realContentHeight = 0;

CalculateSizes(popup, context, ref realWidth, ref realHeight, ref realContentWidth, ref realContentHeight);

if (windowManager is not null)
{
int windowWidth;
int windowHeight;
int statusBarHeight;
int navigationBarHeight;
var windowSize = GetWindowSize(windowManager, decorView);

if (OperatingSystem.IsAndroidVersionAtLeast((int)BuildVersionCodes.R))
{
var windowMetrics = windowManager.CurrentWindowMetrics;
var windowInsets = windowMetrics.WindowInsets.GetInsetsIgnoringVisibility(WindowInsets.Type.SystemBars());
windowWidth = windowMetrics.Bounds.Width();
windowHeight = windowMetrics.Bounds.Height();
statusBarHeight = windowInsets.Top;
navigationBarHeight = windowHeight < windowWidth ? windowInsets.Left + windowInsets.Right : windowInsets.Bottom;
}
else if (windowManager.DefaultDisplay is null)
{
throw new InvalidOperationException($"{nameof(IWindowManager)}.{nameof(IWindowManager.DefaultDisplay)} cannot be null");
}
else
{
APoint realSize = new();
APoint displaySize = new();
ARect contentRect = new();

windowManager.DefaultDisplay.GetRealSize(realSize);
windowManager.DefaultDisplay.GetSize(displaySize);
decorView.GetWindowVisibleDisplayFrame(contentRect);

windowWidth = realSize.X;
windowHeight = realSize.Y;
statusBarHeight = contentRect.Top;

navigationBarHeight = realSize.Y < realSize.X
? (realSize.X - displaySize.X)
: (realSize.Y - displaySize.Y);
}

realWidth = realWidth <= (windowWidth - (windowHeight < windowWidth ? navigationBarHeight : 0)) ? realWidth : (int)(windowWidth - (windowHeight < windowWidth ? navigationBarHeight : 0));
realHeight = realHeight <= (windowHeight - ((windowHeight < windowWidth ? 0 : navigationBarHeight) + statusBarHeight)) ? realHeight : (int)(windowHeight - ((windowHeight < windowWidth ? 0 : navigationBarHeight) + statusBarHeight));
window.SetLayout(realWidth, realHeight);
}
CalculateSizes(popup, context, windowSize, ref realWidth, ref realHeight, ref realContentWidth, ref realContentHeight);
window.SetLayout(realWidth, realHeight);

var childLayoutParams = (FrameLayout.LayoutParams)(child.LayoutParameters ?? throw new InvalidOperationException($"{nameof(child.LayoutParameters)} cannot be null"));
childLayoutParams.Width = realWidth;
childLayoutParams.Height = realHeight;
child.LayoutParameters = childLayoutParams;

if (realContentWidth > -1)
{
var inputMeasuredWidth = realContentWidth > realWidth ? realWidth : realContentWidth;
container.Measure(inputMeasuredWidth, (int)MeasureSpecMode.Unspecified);
horizontalParams = container.MeasuredWidth;
}
else
{
container.Measure(realWidth, (int)MeasureSpecMode.Unspecified);
horizontalParams = container.MeasuredWidth > realWidth ? realWidth : container.MeasuredWidth;
}

if (realContentHeight > -1)
{
verticalParams = realContentHeight;
}
else
{
var inputMeasuredWidth = realContentWidth > -1 ? horizontalParams : realWidth;
container.Measure(inputMeasuredWidth, (int)MeasureSpecMode.Unspecified);
verticalParams = container.MeasuredHeight > realHeight ? realHeight : container.MeasuredHeight;
}
horizontalParams = realWidth;
verticalParams = realHeight;

var containerLayoutParams = new FrameLayout.LayoutParams(horizontalParams, verticalParams);

Expand Down Expand Up @@ -227,35 +169,94 @@ public static void SetSize(this Dialog dialog, in IPopup popup, in AView contain
container.LayoutParameters = containerLayoutParams;


static void CalculateSizes(IPopup popup, Context context, ref int realWidth, ref int realHeight, ref int realContentWidth, ref int realContentHeight)
static void CalculateSizes(IPopup popup, Context context, Size windowSize, ref int realWidth, ref int realHeight, ref int realContentWidth, ref int realContentHeight)
{
ArgumentNullException.ThrowIfNull(popup.Content);

if (!popup.Size.IsZero)
{
realWidth = (int)context.ToPixels(popup.Size.Width);
realHeight = (int)context.ToPixels(popup.Size.Height);
}
if (double.IsNaN(popup.Content.Width) || double.IsNaN(popup.Content.Height))
var density = context.Resources?.DisplayMetrics?.Density ?? throw new InvalidOperationException($"Unable to determine density. {nameof(context.Resources.DisplayMetrics)} cannot be null");

if (popup.Size.IsZero)
{
var size = popup.Content.Measure(double.PositiveInfinity, double.PositiveInfinity);
realContentWidth = (int)context.ToPixels(size.Width);
realContentHeight = (int)context.ToPixels(size.Height);
if (double.IsNaN(popup.Content.Width) || double.IsNaN(popup.Content.Height))
{
var size = popup.Content.Measure(windowSize.Width / density, windowSize.Height / density);
realContentWidth = (int)context.ToPixels(size.Width);
realContentHeight = (int)context.ToPixels(size.Height);

if (double.IsNaN(popup.Content.Width))
{
realContentWidth = popup.HorizontalOptions == LayoutAlignment.Fill ? (int)windowSize.Width : realContentWidth;
}
if (double.IsNaN(popup.Content.Height))
{
realContentHeight = popup.VerticalOptions == LayoutAlignment.Fill ? (int)windowSize.Height : realContentHeight;
}
}
else
{
realContentWidth = (int)context.ToPixels(popup.Content.Width);
realContentHeight = (int)context.ToPixels(popup.Content.Height);
}
}
else
{
realContentWidth = (int)context.ToPixels(popup.Content.Width);
realContentHeight = (int)context.ToPixels(popup.Content.Height);
realWidth = (int)context.ToPixels(popup.Size.Width);
realHeight = (int)context.ToPixels(popup.Size.Height);
}

realWidth = realWidth is 0 ? realContentWidth : realWidth;
realHeight = realHeight is 0 ? realContentHeight : realHeight;
realWidth = Math.Min(realWidth is 0 ? realContentWidth : realWidth, (int)windowSize.Width);
realHeight = Math.Min(realHeight is 0 ? realContentHeight : realHeight, (int)windowSize.Height);

if (realHeight is 0 || realWidth is 0)
{
realWidth = (int)(context.Resources?.DisplayMetrics?.WidthPixels * 0.8 ?? throw new InvalidOperationException($"Unable to determine width. {nameof(context.Resources.DisplayMetrics)} cannot be null"));
realHeight = (int)(context.Resources?.DisplayMetrics?.HeightPixels * 0.6 ?? throw new InvalidOperationException($"Unable to determine height. {nameof(context.Resources.DisplayMetrics)} cannot be null"));
}

popup.Content.Measure(realWidth / density, realHeight / density);
}

static Size GetWindowSize(IWindowManager? windowManager, ViewGroup decorView)
{
ArgumentNullException.ThrowIfNull(windowManager);

int windowWidth;
int windowHeight;
int statusBarHeight;
int navigationBarHeight;

if (OperatingSystem.IsAndroidVersionAtLeast((int)BuildVersionCodes.R))
{
var windowMetrics = windowManager.CurrentWindowMetrics;
var windowInsets = windowMetrics.WindowInsets.GetInsetsIgnoringVisibility(WindowInsets.Type.SystemBars());
windowWidth = windowMetrics.Bounds.Width();
windowHeight = windowMetrics.Bounds.Height();
statusBarHeight = windowInsets.Top;
navigationBarHeight = windowHeight < windowWidth ? windowInsets.Left + windowInsets.Right : windowInsets.Bottom;
}
else if (windowManager.DefaultDisplay is null)
{
throw new InvalidOperationException($"{nameof(IWindowManager)}.{nameof(IWindowManager.DefaultDisplay)} cannot be null");
}
else
{
windowManager.DefaultDisplay.GetRealSize(realSize);
windowManager.DefaultDisplay.GetSize(displaySize);
decorView.GetWindowVisibleDisplayFrame(contentRect);

windowWidth = realSize.X;
windowHeight = realSize.Y;
statusBarHeight = contentRect.Top;

navigationBarHeight = realSize.Y < realSize.X
? (realSize.X - displaySize.X)
: (realSize.Y - displaySize.Y);
}

windowWidth = (windowWidth - (windowHeight < windowWidth ? navigationBarHeight : 0));
windowHeight = (windowHeight - ((windowHeight < windowWidth ? 0 : navigationBarHeight) + statusBarHeight));

return new Size(windowWidth, windowHeight);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Runtime.InteropServices;
using CommunityToolkit.Maui.Core.Extensions;
using Microsoft.Maui;
using Microsoft.Maui.Platform;
using ObjCRuntime;

namespace CommunityToolkit.Maui.Core.Views;
/// <summary>
Expand All @@ -16,18 +15,54 @@ public static class PopupExtensions
/// <param name="popup">An instance of <see cref="IPopup"/>.</param>
public static void SetSize(this MauiPopup mauiPopup, in IPopup popup)
{
if (!popup.Size.IsZero)
ArgumentNullException.ThrowIfNull(popup.Content);

CGRect frame;

if (mauiPopup.ViewController?.View?.Window is UIWindow window)
{
frame = window.Frame;
}
else
{
frame = UIScreen.MainScreen.Bounds;
}

CGSize currentSize;

if (popup.Size.IsZero)
{
mauiPopup.PreferredContentSize = new CGSize(popup.Size.Width, popup.Size.Height);
if (double.IsNaN(popup.Content.Width) || double.IsNaN(popup.Content.Height))
{
var content = popup.Content.ToPlatform(popup.Handler?.MauiContext ?? throw new InvalidOperationException($"{nameof(popup.Handler.MauiContext)} Cannot Be Null"));
var contentSize = content.SizeThatFits(new CGSize(frame.Width, frame.Height));
var width = contentSize.Width;
var height = contentSize.Height;

if (double.IsNaN(popup.Content.Width))
{
width = popup.HorizontalOptions == Microsoft.Maui.Primitives.LayoutAlignment.Fill ? frame.Size.Width : width;
}
if (double.IsNaN(popup.Content.Height))
{
height = popup.VerticalOptions == Microsoft.Maui.Primitives.LayoutAlignment.Fill ? frame.Size.Height : height;
}

currentSize = new CGSize(width, height);
}
else
{
currentSize = new CGSize(popup.Content.Width, popup.Content.Height);
}
}
else if (popup.Content is not null)
else
{
var content = popup.Content;
var measure = popup.Content.Measure(double.PositiveInfinity, double.PositiveInfinity);
var width = content.Width.IsZeroOrNaN() ? measure.Width : content.Width;
var height = content.Height.IsZeroOrNaN() ? measure.Height : content.Height;
mauiPopup.PreferredContentSize = new CGSize(width, height);
currentSize = new CGSize(popup.Size.Width, popup.Size.Height);
}

currentSize.Width = NMath.Min(currentSize.Width, frame.Size.Width);
currentSize.Height = NMath.Min(currentSize.Height, frame.Size.Height);
mauiPopup.PreferredContentSize = currentSize;
}

/// <summary>
Expand Down