Skip to content

Change in Popup Size measurement method#1520

Closed
cat0363 wants to merge 13 commits intoCommunityToolkit:mainfrom
cat0363:Issue-1489
Closed

Change in Popup Size measurement method#1520
cat0363 wants to merge 13 commits intoCommunityToolkit:mainfrom
cat0363:Issue-1489

Conversation

@cat0363
Copy link
Copy Markdown
Contributor

@cat0363 cat0363 commented Nov 15, 2023

This PR resolves an issue where the TextAlignment of a button label placed in a StackLayout is displayed in an unintended position.
It also resolves the issue where the TextAlignment of buttons placed in StackLayout and Grid appears in unintended positions when the device is rotated.

Description of Change

The cause of this problem is that the platform's Measure method is called without considering Maui's LayoutOptions to determine the Popup size. When you call the platform's Measure method, the size of controls placed in StackLayout, VerticalStackLayout, HorizontalStackLayout, and Grid is not measured to the intended size.

In order to call the Measure method taking LayoutOptions into account, the SetSize method in the following locations has been abolished.

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

Also, I have removed calls to the SetSize and SetAnor methods that are called in the following places:

[src\CommunityToolkit.Maui.Core\Handlers\Popup\PopUpHandler.android.cs]

Instead, I changed it to call the SetSize SetAnchor method at the location below.

[src\CommunityToolkit.Maui\Views\Popup\Popup.shared.cs]

#if ANDROID
void OnHandlerChanged(object? sender, EventArgs e)
{
    if (sender is Popup vPopup)
    {
        if (vPopup.Handler?.MauiContext is IMauiContext mauiContext)
        {
            var platformPopup = vPopup.ToHandler(mauiContext);
            if (platformPopup.PlatformView is Dialog dialog &&
                platformPopup.VirtualView is IPopup pPopup &&
                pPopup.Content?.ToPlatform(mauiContext) is AView container)
            {
                container.LayoutChange += (s, le) =>
                {
                    PopupExtensions.SetSize(dialog, vPopup, pPopup, container);
                    CommunityToolkit.Maui.Core.Views.PopupExtensions.SetAnchor(dialog, pPopup);
                };
            }
        }
    }
}

void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(Size))
    {
        if (sender is Popup vPopup)
        {
            if (vPopup.Handler?.MauiContext is IMauiContext mauiContext)
            {
                var platformPopup = vPopup.ToHandler(mauiContext);
                if (platformPopup.PlatformView is Dialog dialog &&
                    platformPopup.VirtualView is IPopup pPopup &&
                    pPopup.Content?.ToPlatform(mauiContext) is AView container)
                {
                    PopupExtensions.SetSize(dialog, vPopup, pPopup, container);
                    CommunityToolkit.Maui.Core.Views.PopupExtensions.SetAnchor(dialog, pPopup);
                }
            }
        }
    }
}
#endif

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

static void PlatformShowPopup(Page page, Popup popup)
{
    var mauiContext = GetMauiContext(page);
    popup.Parent = PageExtensions.GetCurrentPage(page);
    var platformPopup = popup.ToHandler(mauiContext);
    platformPopup.Invoke(nameof(IPopup.OnOpened));

    if (platformPopup.PlatformView is Dialog dialog &&
        platformPopup.VirtualView is IPopup pPopup &&
        pPopup.Content?.ToPlatform(mauiContext) is AView container)
    {
        PopupExtensions.SetSize(dialog, popup, pPopup, container);
    }
}

static Task<object?> PlatformShowPopupAsync(Page page, Popup popup)
{
    PlatformShowPopup(page, popup);
    return popup.Result;
}

I defined a new SetSize method in the location below.

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

By defining the SetSize method in the above location, Maui's LayoutOptions can be referenced and exact size calculations can be performed. See implementation for details.

I changed the way the Measure method is called for each of StackLayout, VerticalStackLayout, HorizontalStackLayout, and Grid.
If Padding is set for Popup's Content, Button's TextAlignment will be misaligned, so we take Padding into consideration.

Linked Issues

PR Checklist

Additional information

Below are the verification results.

[No.1]

<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_VerifyPopupAndroid.PopupPage1"
    Color="Transparent" Size="300,300" HorizontalOptions="Center" VerticalOptions="Center">
    <Grid>
        <Label Text="Hello, World!" FontSize="32" BackgroundColor="LightBlue" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" />
        <Button Text="Click me" VerticalOptions="Start" HorizontalOptions="Center" />
    </Grid>
</toolkit:Popup>

[No.2]

<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_VerifyPopupAndroid.PopupPage2" 
    Size="100,100" HorizontalOptions="Start" VerticalOptions="Center">
    <Grid>
        <Grid.GestureRecognizers>
            <TapGestureRecognizer  Tapped="gd_Tapped" />
        </Grid.GestureRecognizers>
        <Label Text="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ" TextColor="Black" HorizontalOptions="Start" />
    </Grid>
</toolkit:Popup>

[No.3]

<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_VerifyPopupAndroid.PopupPage3" 
    Size="100,100" HorizontalOptions="End" VerticalOptions="End">
    <Grid>
        <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>

[No.4] (Test to dynamically change the label in Popup's Content)

<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_VerifyPopupAndroid.PopupPage4"
    HorizontalOptions="Center" VerticalOptions="Center">
    <Grid>
        <Grid ColumnDefinitions="*" RowDefinitions="auto,auto,auto" >
            <Label x:Name="testlabel1" BackgroundColor="Red" HorizontalTextAlignment="Center"/>
            <Label x:Name="testlabel2" Grid.Row="1" />
            <VerticalStackLayout Grid.Row="2" Spacing="4">
                <Label x:Name="testlabel3" BackgroundColor="Red" HorizontalTextAlignment="Center"/>
                <Label x:Name="testlabel4" />
            </VerticalStackLayout>
        </Grid>
        <Grid WidthRequest="10" HeightRequest="10" BackgroundColor="Blue" VerticalOptions="Start" HorizontalOptions="Start" />
        <Grid WidthRequest="10" HeightRequest="10" BackgroundColor="Blue" VerticalOptions="Start" HorizontalOptions="End" />
        <Grid WidthRequest="10" HeightRequest="10" BackgroundColor="Blue" VerticalOptions="End" HorizontalOptions="Start" />
        <Grid WidthRequest="10" HeightRequest="10" BackgroundColor="Blue" VerticalOptions="End" HorizontalOptions="End" />
    </Grid>
</toolkit:Popup>

[No.5] (Test to set a long string to the label text in Popup's Content)

<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_VerifyPopupAndroid.PopupPage5"
    HorizontalOptions="Center" VerticalOptions="Center">
    <VerticalStackLayout>
        <Label Text="Popup" FontSize="20"/>
        <BoxView HeightRequest="3" Color="AliceBlue" />
        <Label x:Name="txt1" Text="Short String" />
        <Label x:Name="txt2" Text="Long String1 Long String2 Long String3 Long String4 Long String5 Long String6 Long String7 Long String8 Long String9 Long String10 Long String" />
    </VerticalStackLayout>
</toolkit:Popup>

[No.6] Test for rounding popup corners

<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_VerifyPopupAndroid.PopupPage6" 
    Size="200,200" HorizontalOptions="Center" VerticalOptions="Center" Color="Transparent">
    <Border StrokeShape="RoundRectangle 5,5,5,5" BackgroundColor="Red" StrokeThickness="0">        
        <Grid 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>
    </Border>
</toolkit:Popup>

[No.7]

<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_VerifyPopupAndroid.PopupPage7"
    HorizontalOptions="Start" VerticalOptions="Start">
    <Grid>
        <ScrollView>
            <StackLayout>
                <Image Source="dotnet_bot.png" HeightRequest="200" />
                <Label Text="Hello, World!" HorizontalTextAlignment="Center" />
            </StackLayout>
        </ScrollView>
    </Grid>
</toolkit:Popup>

The result is similar to the .NET MAUI side. This behavior cannot be changed. An explicit size must be specified.

[No.8] (This is a test for Issue #1489.)

<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_VerifyPopupAndroid.PopupPage8"
    HorizontalOptions="Center" VerticalOptions="Center">
    <VerticalStackLayout>
        <Label x:Name="PopUp" Text="     Critical Alert Testing     " BackgroundColor="White" TextColor="Black" FontSize="Medium" VerticalOptions="Center" HorizontalOptions="Center" />
        <Button x:Name="Button_Continue" Text=" Continue " BackgroundColor="Red" TextColor="White" FontSize="Large" />
    </VerticalStackLayout>
</toolkit:Popup>
Android.Emulator.-.pixel_2_-_api_30_5554.2023-11-15.17-14-07.mp4

Below is the execution result after rotating the device.

[No.9] (Testing VerticalStackLayout.)

<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_VerifyPopupAndroid.PopupPage9"
    HorizontalOptions="Center" VerticalOptions="Center">
    <VerticalStackLayout>
        <Label x:Name="PopUp" Text="     Critical Alert Testing     " BackgroundColor="White" TextColor="Black" FontSize="Medium" VerticalOptions="Center" HorizontalOptions="Center" />
        <Button Text="ABC" BackgroundColor="Red" TextColor="White" FontSize="Large" HorizontalOptions="Start" />
        <Button Text="CDE" BackgroundColor="Red" TextColor="White" FontSize="Large" HorizontalOptions="Center" />
        <Button Text="EDF" BackgroundColor="Red" TextColor="White" FontSize="Large" HorizontalOptions="End" />
        <Button Text="HIJ" BackgroundColor="Red" TextColor="White" FontSize="Large" HorizontalOptions="Fill" />
    </VerticalStackLayout>
</toolkit:Popup>

[No.10] (Testing HorizontalStackLayout.)

<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_VerifyPopupAndroid.PopupPage10"
    HorizontalOptions="End" VerticalOptions="Center">
    <VerticalStackLayout>
        <Label x:Name="PopUp" Text="     Critical Alert Testing     " BackgroundColor="White" TextColor="Black" FontSize="Medium" VerticalOptions="Center" HorizontalOptions="Center" />
        <HorizontalStackLayout HeightRequest="132">
            <Button Text="ABC" BackgroundColor="Red" TextColor="White" FontSize="Large" VerticalOptions="Start" WidthRequest="100" />
            <Button Text="CDE" BackgroundColor="Red" TextColor="White" FontSize="Large" VerticalOptions="Center" />
            <Button Text="EDF" BackgroundColor="Red" TextColor="White" FontSize="Large" VerticalOptions="End" />
            <Button Text="HIJ" BackgroundColor="Red" TextColor="White" FontSize="Large" VerticalOptions="Fill" />
        </HorizontalStackLayout>
    </VerticalStackLayout>
</toolkit:Popup>

[No.11] (Testing Grid.)

<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_VerifyPopupAndroid.PopupPage11"
    Size="300,300" HorizontalOptions="End" VerticalOptions="End">
    <Grid RowDefinitions="44,*" ColumnDefinitions="100,*">
        <Button Grid.Row="0" Grid.Column="0" Text="ABC" BackgroundColor="Red" />
        <Button Grid.Row="0" Grid.Column="1" Text="CDE" HorizontalOptions="Start" VerticalOptions="Start" />
        <Button Grid.Row="1" Grid.Column="0" Text="EFG" />
        <Button Grid.Row="1" Grid.Column="1" Text="HIJ" HorizontalOptions="End" VerticalOptions="End" />
    </Grid>
</toolkit:Popup>

[No.12]

<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_VerifyPopupAndroid.PopupPage12"
    Size="200,50" HorizontalOptions="End" VerticalOptions="Start">
    <Button Text="Test" BackgroundColor="Red" />
</toolkit:Popup>

You can see that the Popup is displayed as intended in both layouts.

Note:
This PR takes padding into consideration, so please check if the padding in CommunityToolkit's PopupLayout is what you intended.
Due to insufficient consideration of PR #1456, Popups were not displayed as per the layout on the Android side for a long time.
This is mainly a Popup sample.

This PR makes major changes to how controls within Popups are measured. If you do not accept this change, you may want to reconsider reverting the code in PR #1456. Display issues on Android are caused by insufficient consideration of PR #1456.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 15, 2023

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 17, 2023

Modify some conditions. It is currently being verified.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 17, 2023

Adding a condition when the target's Parent is ReorderItemView solves the CollectionView display problem.
I will upload the corrected code now. Sorry for the very dirty code.
I hope that people who understand the real meaning of this problem will write better code.

Android.Emulator.-.pixel_2_-_api_30_5554.2023-11-17.10-08-18.mp4

Issue #1532 should be resolved with this fix.

@pictos
Copy link
Copy Markdown
Member

pictos commented Nov 17, 2023

Hey @cat0363, thanks for that... Basically you need to have access to the Maui world, but the code that you put inside the shared layer is just for android, and that doesn't make too much sense, using the shared to control to call the handler/platform control.

What you can is to create a Handler.Imp on the CommunityToolkit.Maui project and add the logic there. Also, why this change is just for Android, other platforms works well with the way we're doing?

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 17, 2023

@pictos , Thank you for the advice. I had made a big mistake.
Does that mean I need to implement the following?
[src\CommunityToolkit.Maui\HandlerImplementation\Popup\Popup.android.cs]

I haven't fully investigated the details of how the Measure method works on other platforms.
There is no specification like MeasureSpecMode, at least on other platforms.

Only Android has a MeasureSpecMode specification, and if you don't specify anything and just pass the width and height to the Measure method, it will behave as MeasureSpecMode.Unspecified, so this is the cause of the problem in Android.
Therefore, if you call the Measure method without specifying MeasureSpecMode, the parent will not impose size restrictions on the child, and the display will not reflect Maui's LayoutOptions.
LayoutOptions are not accurately reflected, so it will be displayed at an unintended size. That's my view.

At this point, we do not know if there are any issues with platforms other than Android.
If it works well on a platform other than Android, we may need to look into how Maui sets the values ​​needed to measure the size.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 17, 2023

In Windows, there were cases where there was a problem when the Popup size was not specified.
It's different from Windows, but iOS is similar.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 22, 2023

I found a solution to the problem where Popup is displayed at an unintended size when you do not specify an explicit size on Windows.
As for iOS, I've been busy and haven't been able to research it yet.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 24, 2023

If the Popup size is not specified and the Label Text is dynamically changed, it will not be redrawn on iOS.
Therefore, case No. 4 will not be drawn at the intended size.
It is possible to force a redraw using the Text property change notification, but I am not sure if this is correct or not.

iPhone.14.iOS.16.4.2023-11-24.12-09-47.mp4

I can't think of any other way because I can't detect changes in the size of child elements on the iOS side.
By the way, if you redraw after receiving a change notification for the Width and Height properties, the display will be unintended.
It feels really bad that it has to be a Text property.

@cat0363 cat0363 changed the title Change in Popup Size measurement method on Android Change in Popup Size measurement method Nov 29, 2023
@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 29, 2023

Addressed popup size issues on Android, iOS, and Windows.
Issue #1516 should be resolved with the fix posted today.
Popup position and size are now adjusted according to window resizing on Windows.
Only on iOS, the platform cannot detect size changes based on changes in the Label's
Text, so the size is updated by notification of changes in the Text property.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Nov 29, 2023

I need to consider the StrokeThickness and Padding of the Border control, so we will reconsider it.
In the modified code uploaded today, there is a problem with AvatarView whose parent class is Border.

namespace CommunityToolkit.Maui.Views;

public partial class Popup
public partial class Popup : Element
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this's using the shared layer instead of the Handler and the MapSize?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pictos , Since it was unclear how to detect the size change event of the child element of Popup's Content, I implemented it in the shared layer.
If it is possible to detect changes in the size of child elements as the text changes, there is no need to implement it in the shared layer.
Is there any better way?

At least if I didn't implement it like this, No. 4 wouldn't work.
In the case where the Popup's size is unspecified and it resizes according to the dynamic resizing of Content's child elements.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pictos Just curious - what's the downside to making Popup inherit from Element.

Looking at the .NET MAUI repo, every control that appears on the screen inherits from VisualElement (e.g. Button, Label, etc, all inherit from VisualElement).

For Popup, I'd say it may make even more sense to have it inherit from VisualElement to better align with how .NET MAUI creates controls.

Copy link
Copy Markdown
Member

@pictos pictos Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brminnick answering your questions...

@pictos Just curious - what's the downside to making Popup inherit from Element.

All the downside possibles, hehe... The .NET MAUI team gave more love to VisualElement instead of Element, the good part from the community is that Shane made a lot of improvements on Element because of poups, and now everyone in the community will have a happy place where they need to implement controls that inherit from Element.

For Popup, I'd say it may make even more sense to have it inherit from VisualElement to better align with how .NET MAUI creates controls.

Would be great if we could do it, but we are blocked on that because of the current .NET MAUI restrictions on what can be a VisualElement. So, every control that inherits from VisualElement its native part will inherit from ViewHandler, Basically just controls that are inherited from the platform View can be a VisualElement. Our popup implementation follows what each platform defines what's a popup, For android it's a Dialog and for iOS a UIViewController is used, and none of those inherit from platform View, with that, we can't make the PopupHandler a ViewHandler and because of that the Popup can't be a VisualElement.

But again, @PureWeen made a lot of improvements to make Element a first-class citizen on .net Maui custom controls. We basically need to make usage of the new APIs, like this one, as you can see on description, Shane used the Popup as showcase

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it! Thanks for the details!!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we assign it to the Content.SizeChanged and call the MapSize from there? MY plan here is to make this control aligned with the .NET MAUI way to do things, that way if this control is promoted to be in the Maui framework will be easier to port it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pictos , Thank you for suggesting the amendment.
Fixed to call SetSize method in Content.SizeChanged.

public static void MapSize(PopupHandler handler, IPopup view)
{
ArgumentNullException.ThrowIfNull(handler.Container);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this method after removing the code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MapSize method is not needed as a similar implementation is done within the OnPropertyChanged method.

[src\CommunityToolkit.Maui\HandlerImplementation\Popup\Popup.android.cs]

void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(Size))
    {
        if (Handler?.MauiContext is IMauiContext mauiContext)
        {
            var platformPopup = this.ToHandler(mauiContext);
            if (platformPopup.PlatformView is Dialog dialog &&
                platformPopup.VirtualView is IPopup pPopup &&
                pPopup.Content?.ToPlatform(mauiContext) is AView container)
            {
                SetSize(dialog, this, pPopup, container);
                CommunityToolkit.Maui.Core.Views.PopupExtensions.SetAnchor(dialog, pPopup);
            }
        }
    }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, since the MapSize method was being called when the VerticalOptions and HorizontalOptions properties were changed, it is necessary to correct it as shown below.

[src\CommunityToolkit.Maui\HandlerImplementation\Popup\Popup.android.cs]

void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(Size) ||
        e.PropertyName == nameof(HorizontalOptions) ||
        e.PropertyName == nameof(VerticalOptions))
    {
        if (Handler?.MauiContext is IMauiContext mauiContext)
        {
            var platformPopup = this.ToHandler(mauiContext);
            if (platformPopup.PlatformView is Dialog dialog &&
                platformPopup.VirtualView is IPopup pPopup &&
                pPopup.Content?.ToPlatform(mauiContext) is AView container)
            {
                SetSize(dialog, this, pPopup, container);
                CommunityToolkit.Maui.Core.Views.PopupExtensions.SetAnchor(dialog, pPopup);
            }
        }
    }
}

[src\CommunityToolkit.Maui\HandlerImplementation\Popup\Popup.windows.cs]

void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == nameof(Size) ||
        e.PropertyName == nameof(HorizontalOptions) ||
        e.PropertyName == nameof(VerticalOptions))
    {
        if (Handler?.MauiContext is IMauiContext mauiContext)
        {
            var platformPopup = this.ToHandler(mauiContext);
            if (platformPopup.PlatformView is Microsoft.UI.Xaml.Controls.Primitives.Popup dialog &&
                platformPopup.VirtualView is IPopup pPopup &&
                pPopup.Content?.ToPlatform(mauiContext) is Microsoft.UI.Xaml.FrameworkElement container)
            {
                SetSize(dialog, this, pPopup, mauiContext, container);
                CommunityToolkit.Maui.Core.Views.PopupExtensions.SetLayout(dialog, pPopup, mauiContext);
            }
        }
    }
}

[src\CommunityToolkit.Maui.Core\Handlers\Popup\PopupHandler.shared.cs]

public static IPropertyMapper<IPopup, PopupHandler> PopUpMapper = new PropertyMapper<IPopup, PopupHandler>(ElementMapper)
{
    [nameof(IPopup.Anchor)] = MapAnchor,
    [nameof(IPopup.Color)] = MapColor,
#if IOS || MACCATALYST || TIZEN
    [nameof(IPopup.Size)] = MapSize,
    [nameof(IPopup.VerticalOptions)] = MapSize,
    [nameof(IPopup.HorizontalOptions)] = MapSize,
#endif
    [nameof(IPopup.CanBeDismissedByTappingOutsideOfPopup)] = MapCanBeDismissedByTappingOutsideOfPopup
};

Therefore, the MapSize method is not required on Windows and Android.
The following must be removed.

[src\CommunityToolkit.Maui.Core\Handlers\Popup\PopUpHandler.android.cs]

public static void MapSize(PopupHandler handler, IPopup view)
{
    ArgumentNullException.ThrowIfNull(handler.Container);
}

[src\CommunityToolkit.Maui.Core\Handlers\Popup\PopUpHandler.windows.cs]

public static void MapSize(PopupHandler handler, IPopup view)
{

}

I will update the fix after verifying operation.

#if ANDROID || WINDOWS
AddHandlerChanged();
AddPropertyChanged();
#elif IOS
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MacCatalyst?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VladislavAntonyuk , As you pointed out, MacCatalyst is required.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Dec 13, 2023

Modify the implementation on the Windows side to reduce the number of changes.

@ghost ghost added stale The author has not responded in over 30 days help wanted This proposal has been approved and is ready to be implemented labels Jan 13, 2024
@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Jan 29, 2024

As Shane mentions in Issue 1664, this PR's approach is wrong because calling the Measure method outside of the layout cycle produces unintended results on Android.

Therefore, this PR should not be applied.

I am very sorry that I have come to this conclusion after receiving various points.

At the moment, I can't think of a way to get the exact size of a Popup without calling the Measure method outside of the layout cycle.

@TheCodeTraveler
Copy link
Copy Markdown
Collaborator

Thanks for following up @cat0363!

Therefore, this PR should not be applied.

Bummer! No worries. I'll close this PR.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Jan 29, 2024

@brminnick , Thank you for your reply.
I have decided that it is not a good idea to continue blocking this problem without being able to come up with a new solution.
It may take some time, but I'll try to find a better way. At that time, I will create a new PR.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Jan 31, 2024

I'm currently testing it, but I've found a new solution. Regarding No.7, this solution does not solve the problem.
The intended layout is now achieved without calling the Measure method of each node on the visual tree.
However, this solution results in calling the Measure method only on the root node on the visual tree.
I will finally test it with a nightly build of .net maui and if there are no problems, I will create a PR.
Since I reverted to an older version and rewrote the code, I am currently considering how to apply it to the latest version.

@Kas-code
Copy link
Copy Markdown

Kas-code commented Feb 6, 2024

@cat0363 Just a note of support - thank you for continuing to work on this.
Issue 1603 is causing issues on my project, so please let me know if there is anything I can do to help progress this along.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Feb 7, 2024

@Kas-code , In addition to the Popup size issue, I am currently verifying a solution to the display position issue after screen rotation when specifying Anchor for the Popup.
I can't provide a solution to this problem by reimplementing Handler.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Feb 7, 2024

Now that I have completed the verification, I will create a PR starting tomorrow.
This will take some time, so please be patient.

@cat0363
Copy link
Copy Markdown
Contributor Author

cat0363 commented Feb 8, 2024

I just uploaded a PR. Thank you for allowing me to take on the challenge again.
I can't devote any more time to this issue, so I hope others come up with a better solution if this fix is ​​unacceptable.

@github-actions github-actions Bot locked and limited conversation to collaborators Nov 20, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

help wanted This proposal has been approved and is ready to be implemented stale The author has not responded in over 30 days

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] CommunityToolkit.Maui.Views.Popup Button Text Alignment

5 participants