Maui
Maui copied to clipboard
[BUG] Popup layout is broken
Is there an existing issue for this?
- [X] I have searched the existing issues
Did you read the "Reporting a bug" section on Contributing file?
- [X] I have read the "Reporting a bug" section on Contributing file: https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md#reporting-a-bug
Current Behavior
First – I’m sorry, I can’t provide a repository. I’m not allowed to upload a repository by company policy, and I’ve created my Github account only to report bugs. But the steps to reproduce the layout problems of the Popup are very straight forward and I hope, you can fix this anyways: The layout of the Popup is broken.
Expected Behavior
The layout of the Popup should work.
Steps To Reproduce
This is, what I want to get:
<StackLayout Padding="10" Spacing="6">
<Button Text="Menüeintrag 1"/>
<Button Text="Menüeintrag 2"/>
<Button Text="Menüeintrag 3"/>
<Button Text="Menüeintrag 4"/>
<Button Text="Menüeintrag 5"/>
<Button Text="Menüeintrag 6"/>
<Button Text="Menüeintrag 7"/>
<Button Text="Menüeintrag 8"/>
<Button Text="Menüeintrag 9"/>
<Button Text="Menüeintrag 10"/>
</StackLayout>
The Popup adjusts its Width to the content – because the Width can be different in different languages or situations. This works fine. But I also want to be able to scroll the items in landscape mode. So I put the StackLayout into a ScrollView:
<ScrollView>
<StackLayout Padding="10" Spacing="6">
<Button Text="Menüeintrag 1"/>
<Button Text="Menüeintrag 2"/>
<Button Text="Menüeintrag 3"/>
<Button Text="Menüeintrag 4"/>
<Button Text="Menüeintrag 5"/>
<Button Text="Menüeintrag 6"/>
<Button Text="Menüeintrag 7"/>
<Button Text="Menüeintrag 8"/>
<Button Text="Menüeintrag 9"/>
<Button Text="Menüeintrag 12"/>
</StackLayout>
</ScrollView>
Now the layout is broken. I’ve reported this bug almost a year ago (https://github.com/CommunityToolkit/Maui/issues/1516), I’ve found a work around. Using DevExpress DXScrollView instead of ScrollView fixes the problem, too. But I think this should work with the MAUI standard controls, as well.
For the second layout issue I sadly don’t have a workaround:
<StackLayout Padding="10" Spacing="6">
<Button Text="Item 1"/>
<Button Text="Item 2"/>
<Button Text="This button has a very long text that is simply cut off in the middle."/>
</StackLayout>
The Popup can’t get wider than 320 Units anymore. The MaximumWidthRequest seems to be limited by this value – hard coded into the Popup control.
Link to public reproduction project repository
https://github.com/CommunityToolkit/Maui
Environment
- .NET MAUI CommunityToolkit: 9.1.0
- OS: Android 14
- .NET MAUI: 8.0.91
Anything else?
Thank you very much for help.
Hi All,
based on this excellent blog post by Redth from the MAUI team, I now use the following PopupPage:
public class PopupPage : ContentPage
{
private View _outerView = null;
private View _innerView = null;
public event EventHandler Closed;
public event EventHandler Clicked;
public static readonly BindableProperty ColorProperty =
BindableProperty.Create(nameof(Color), typeof(Color), typeof(PopupPage), Colors.White);
public static readonly BindableProperty BackdropProperty =
BindableProperty.Create(nameof(Backdrop), typeof(Color), typeof(PopupPage), Colors.Transparent);
public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty =
BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(PopupPage), true);
public static readonly BindableProperty VerticalOptionsProperty =
BindableProperty.Create(nameof(VerticalOptions), typeof(LayoutOptions), typeof(PopupPage), LayoutOptions.Center);
public static readonly BindableProperty HorizontalOptionsProperty =
BindableProperty.Create(nameof(HorizontalOptions), typeof(LayoutOptions), typeof(PopupPage), LayoutOptions.Center);
public static readonly BindableProperty IsAnimatedProperty =
BindableProperty.Create(nameof(IsAnimated), typeof(bool), typeof(PopupPage), true);
public Color Color
{
get => (Color)GetValue(ColorProperty);
set => SetValue(ColorProperty, value);
}
public Color Backdrop
{
get => (Color)GetValue(BackdropProperty);
set => SetValue(BackdropProperty, value);
}
public bool CanBeDismissedByTappingOutsideOfPopup
{
get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty);
set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value);
}
public LayoutOptions VerticalOptions
{
get => (LayoutOptions)GetValue(VerticalOptionsProperty);
set => SetValue(VerticalOptionsProperty, value);
}
public LayoutOptions HorizontalOptions
{
get => (LayoutOptions)GetValue(HorizontalOptionsProperty);
set => SetValue(HorizontalOptionsProperty, value);
}
public bool IsAnimated
{
get => (bool)GetValue(IsAnimatedProperty);
set => SetValue(IsAnimatedProperty, value);
}
public PopupPage() : base()
{
Opacity = 0;
NavigatedTo += PopupPage_NavigatedTo;
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
_outerView = (View)this.GetTemplateChild("Outer_Content");
_innerView = (View)this.GetTemplateChild("Inner_Content");
if (_outerView is object)
{
TapGestureRecognizer tap = new TapGestureRecognizer();
tap.Command = new Command(OnClickedOutside);
_outerView.GestureRecognizers.Add(tap);
}
if (_innerView is object)
{
if (IsAnimated)
_innerView.IsVisible = false;
TapGestureRecognizer tap = new TapGestureRecognizer();
tap.Command = new Command(OnClicked);
_innerView.GestureRecognizers.Add(tap);
}
}
private async void PopupPage_NavigatedTo(object sender, NavigatedToEventArgs e)
{
NavigatedTo -= PopupPage_NavigatedTo;
if (IsAnimated)
await this.FadeTo(1, 250, Easing.Linear);
Opacity = 1;
if (_innerView is object)
_innerView.IsVisible = true;
}
protected override bool OnBackButtonPressed()
{
Close();
return true;
}
protected void OnClicked(object sender)
{
if (Clicked != null)
this.Clicked(this, EventArgs.Empty);
}
protected void OnClickedOutside(object sender)
{
if (CanBeDismissedByTappingOutsideOfPopup)
Close();
}
async Task CloseAsync()
{
if (IsAnimated)
{
if (_innerView is object)
_innerView.IsVisible = false;
await this.FadeTo(0, 250, Easing.Linear);
}
await Navigation.PopModalAsync(animated: false);
Closed?.Invoke(this, EventArgs.Empty);
}
public async void Close()
{
await CloseAsync();
}
}
<ControlTemplate x:Key="PopupPageTemplate">
<ContentView x:Name="Outer_Content" BackgroundColor="{TemplateBinding Backdrop}">
<ContentPresenter x:Name="Inner_Content" Content="{TemplateBinding Content}" BackgroundColor="{TemplateBinding Color}" HorizontalOptions="{TemplateBinding HorizontalOptions}" VerticalOptions="{TemplateBinding VerticalOptions}">
<ContentPresenter.Shadow>
<Shadow Brush="Black" Offset="0,0" Radius="20" Opacity="0.5" />
</ContentPresenter.Shadow>
</ContentPresenter>
</ContentView>
</ControlTemplate>
<Style TargetType="e:PopupPage" ApplyToDerivedTypes="True">
<Setter Property="ControlTemplate" Value="{StaticResource PopupPageTemplate}" />
<Setter Property="Color" Value="White" />
<Setter Property="Backdrop" Value="#40000000" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>