question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] The size and position of Popup is wrong on Android and iOS.

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Did you read the “Reporting a bug” section on Contributing file?

Current Behavior

I won’t mention the difference between Popup’s Margin and CornerRect here.

In order to make it easier to understand the four corners of the Popup, the layout is as follows.

<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    x:Class="MauiComm_IssuePopupSizePosition.PopupPage">
    <Grid VerticalOptions="Fill" HorizontalOptions="Fill" BackgroundColor="Red">
        <Grid WidthRequest="10" HeightRequest="10" VerticalOptions="Start" HorizontalOptions="Start" BackgroundColor="Blue" />
        <Grid WidthRequest="10" HeightRequest="10" VerticalOptions="Start" HorizontalOptions="End" BackgroundColor="Blue" />
        <Grid WidthRequest="10" HeightRequest="10" VerticalOptions="End" HorizontalOptions="Start" BackgroundColor="Blue" />
        <Grid WidthRequest="10" HeightRequest="10" VerticalOptions="End" HorizontalOptions="End" BackgroundColor="Blue" />
    </Grid>
</toolkit:Popup>
popup

Specify the following for Size, HorizontalOptions, VerticalOptions of Popup.

Size = "100, 100"
HorizontalOptions = "Fill"
VerticalOptions = "Fill"

Below are the execution results for Android and iOS.

[Android] [iOS]

Android shows the Popup in the center, iOS shows the Popup in the top left, and in iOS it’s not showing up in the intended position. I was expecting iOS to show a popup in the middle like Android does.

Next, when you specify a size for the popup that exceeds the screen size.

Size = "1000, 1000"

I verified by changing HorizontalOptions and VerticalOptions as follows on Android and iOS.

HorizontalOptions = “Start” VerticalOptions = “Start”

[Android] [iOS]

HorizontalOptions = “Center” VerticalOptions = “Start”

[Android] [iOS]

HorizontalOptions = “End” VerticalOptions = “Start”

[Android] [iOS]

HorizontalOptions = “Fill” VerticalOptions = “Start”

[Android] [iOS]

HorizontalOptions = “Start” VerticalOptions = “Center”

[Android] [iOS]

HorizontalOptions = “Center” VerticalOptions = “Center”

[Android] [iOS]

HorizontalOptions = “End” VerticalOptions = “Center”

[Android] [iOS]

HorizontalOptions = “Fill” VerticalOptions = “Center”

[Android] [iOS]

HorizontalOptions = “Start” VerticalOptions = “End”

[Android] [iOS]

HorizontalOptions = “Center” VerticalOptions = “End”

[Android] [iOS]

HorizontalOptions = “End” VerticalOptions = “End”

[Android] [iOS]

HorizontalOptions = “Fill” VerticalOptions = “End”

[Android] [iOS]

HorizontalOptions = “Start” VerticalOptions = “Fill”

[Android] [iOS]

HorizontalOptions = “Center” VerticalOptions = “Fill”

[Android] [iOS]

HorizontalOptions = “End” VerticalOptions = “Fill”

[Android] [iOS]

HorizontalOptions = “Fill” VerticalOptions = “Fill”

[Android] [iOS]

Everything looks correct on Android, but it is only displayed starting from the top right. I was expected that when I gave a Popup a size greater than the screen size, the size of the Popup would be limited by the screen size.

On iOS, Popups are disappearing or appearing in unintended sizes and positions. Similarly, I was expected that when I gave a Popup a size greater than the screen size, the size of the Popup would be limited by the screen size.

Expected Behavior

If the size of the Popup does not exceed the screen size, I was expected it to be displayed in the center if Fill is specified for HorizontalOptions and VerticalOptions.

[iOS]

I was expected the Popup’s size to be limited to the screen size if the Popup’s size exceeds the screen size.

[Android] [iOS]

Steps To Reproduce

The steps to reproduce are as follows.

[Case 1]

  1. Launch the app uploaded to github with the device on iOS
  2. Set With to 100, Height to 100, HorizontalOptions to Fill, VerticalOptions to Fill
  3. Press Show button

[Case 2]

  1. Launch the app uploaded to github with the device on iOS
  2. Set With to 1000, Height to 1000
  3. Select any HorizontalOptions
  4. Select any VerticalOptions
  5. Press Show Button

Link to public reproduction project repository

https://github.com/cat0363/MauiComm-IssuePopupSizePosition.git

Environment

- .NET MAUI CommunityToolkit: 5.2.0
- OS: iOS 16.4, Android 11.0
- .NET MAUI: 7.0.92

Anything else?

No response

Issue Analytics

  • State:closed
  • Created 2 months ago
  • Reactions:1
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
brminnickcommented, Aug 3, 2023

Thanks @cat0363!

Could you please submit a PR with the bug fix?

1reaction
cat0363commented, Aug 3, 2023

This issue can be resolved by modifying as follows.

Below is the modified code on the Android side.

[src\CommunityToolkit.Maui.Core\Views\Popup\PopupExtensions.android.cs]

public static void SetSize(this Dialog dialog, in IPopup popup, in AView container)
{
    ArgumentNullException.ThrowIfNull(popup.Content);

    int horizontalParams, verticalParams;

    var window = GetWindow(dialog);
    var context = dialog.Context;
    var decorView = (ViewGroup)window.DecorView;
    var child = decorView.GetChildAt(0) ?? throw new NullReferenceException();
    var win = context.GetWindow();
    var density = context.GetDisplayDensity();

    int realWidth = 0,
    realHeight = 0,
    realContentWidth = 0,
    realContentHeight = 0;

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

    if (win is not null)
    {
        realWidth = realWidth <= win.Width * density ? realWidth : (int)(win.Width * density);
        realHeight = realHeight <= win.Height * density ? realHeight : (int)(win.Height * density);
        window.SetLayout(realWidth, realHeight);
    }

    ... omit

}

Below is the modified code on the iOS side.

[src\CommunityToolkit.Maui.Core\Views\Popup\PopupExtensions.macios.cs]

public static void SetLayout(this MauiPopup mauiPopup, in IPopup popup)
{
    if (mauiPopup.View is null)
    {
        return;
    }

    CGRect frame;

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

    if (mauiPopup.PopoverPresentationController is null)
    {
        throw new InvalidOperationException("PopoverPresentationController cannot be null");
    }

    if (popup.Anchor is null)
    {			
        var originY = popup.VerticalOptions switch
        {
            Microsoft.Maui.Primitives.LayoutAlignment.Start => mauiPopup.PreferredContentSize.Height < frame.Height ? mauiPopup.PreferredContentSize.Height / 2 : -frame.GetMidY(),
            Microsoft.Maui.Primitives.LayoutAlignment.End => mauiPopup.PreferredContentSize.Height < frame.Height ? frame.Height - (mauiPopup.PreferredContentSize.Height / 2) : -frame.GetMidY(),
            Microsoft.Maui.Primitives.LayoutAlignment.Center => mauiPopup.PreferredContentSize.Height < frame.Height ? frame.GetMidY() : -frame.GetMidY(),
            _ => mauiPopup.PreferredContentSize.Height < frame.Height ? frame.GetMidY() : -frame.GetMidY()
        };

        var originX = popup.HorizontalOptions switch
        {
            Microsoft.Maui.Primitives.LayoutAlignment.Start => mauiPopup.PreferredContentSize.Width < frame.Width ? mauiPopup.PreferredContentSize.Width / 2 : -frame.GetMidX(),
            Microsoft.Maui.Primitives.LayoutAlignment.End => mauiPopup.PreferredContentSize.Width < frame.Width ? frame.Width - (mauiPopup.PreferredContentSize.Width / 2) : -frame.GetMidX(),
            Microsoft.Maui.Primitives.LayoutAlignment.Center => mauiPopup.PreferredContentSize.Width < frame.Width ? frame.GetMidX() : -frame.GetMidX(),
            _ => mauiPopup.PreferredContentSize.Width < frame.Width ? frame.GetMidX() : -frame.GetMidX()
        };

        ... omit
    }
    else
    {
        var view = popup.Anchor.ToPlatform(popup.Handler?.MauiContext ?? throw new InvalidOperationException($"{nameof(popup.Handler.MauiContext)} Cannot Be Null"));
        mauiPopup.PopoverPresentationController.SourceView = view;
        mauiPopup.PopoverPresentationController.SourceRect = view.Bounds;
    }
}

I will create a PR after refactoring.

Below is the execution result.

Size = "100, 100"
HorizontalOptions = "Fill"
VerticalOptions = "Fill"
[iOS]
Size = "1000, 1000"
HorizontalOptions = "Start"
VerticalOptions = "Start"
[Android] [iOS]
Size = "300, 1000"
HorizontalOptions = "Start"
VerticalOptions = "Start"
[Android] [iOS]
Size = "300, 1000"
HorizontalOptions = "Center"
VerticalOptions = "Start"
[Android] [iOS]
Size = "300, 1000"
HorizontalOptions = "End"
VerticalOptions = "Start"
[Android] [iOS]
Size = "300, 1000"
HorizontalOptions = "Fill"
VerticalOptions = "Start"
[Android] [iOS]
Read more comments on GitHub >

github_iconTop Results From Across the Web

PopupWindow wrong Y position - android
your screen is e.g. 1000px high and you scroll down two times the screenlength. event.y.toInt() could return now 2000px as a relative y ......
Read more >
Issues with position fixed & scrolling on iOS
Another issue people will find with iOS fixed position elements is the "first broken scroll" issue, where the first time a user scrolls...
Read more >
Work items popup maximized window in Sprints
There's no need to resize popup window cause it's already sizeable. This problem could be easily fixed if the popup window size would...
Read more >
Top 7 Mobile Popup Best Practices to Follow in 2023
1. Choose the right popup type and position. So basically there are a few types of popups, mainly we talk about full-screen and...
Read more >
iOS 16 Problems and Bugs with Fixes in 2023
Some iOS 16 bugs and issues need fixes from Apple. Others you may be able to fix by yourself. When anything goes wrong...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found