Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ static void RegisterViewsAndViewModels(in IServiceCollection services)
services.AddTransientPopup<TransparentPopup>();
services.AddTransientPopup<UpdatingPopup, UpdatingPopupViewModel>();
services.AddTransientPopup<XamlBindingPopup, XamlBindingPopupViewModel>();
services.AddTransientPopup<SoftInputKeyboardPopup>();
}

static void RegisterEssentials(in IServiceCollection services)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ScrollView>
<VerticalStackLayout Spacing="12">
<Button Text="Simple Popup" Clicked="HandleSimplePopupButtonClicked" />

<Button Text="Self Closing Popup" Clicked="HandleSelfClosingPopupButtonClicked"/>

<Button Text="Button Popup" Clicked="HandleButtonPopupButtonClicked" />
Expand All @@ -35,7 +35,7 @@
<Button Text="Updating Popup" Command="{Binding UpdatingPopupCommand}" />

<Button Text="Show Popup content" Command="{Binding ShowPopupContentCommand}" />

<Button Text="Show Popup in a Modal Page in a Custom Navigation Page" Clicked="HandleModalPopupInCustomNavigationPage" />

<Button Text="Custom Positioning Popup" Clicked="HandlePopupPositionButtonClicked" />
Expand All @@ -49,11 +49,13 @@
<Button Text="Popup Style Page" Clicked="HandleStylePopupButtonClicked" />

<Button Text="OnDisappearing Popup" Clicked="HandleOnDisappearingPopupClicked" />

<Button Text="Complex Popup" Clicked="HandleComplexPopupClicked" />

<Button Text="Collection View Popup" Clicked="HandleCollectionViewPopupClicked" />


<Button Text="Software Input Keyboard Popup" Clicked="HandleSoftInputKeyboardPopupClicked" />

</VerticalStackLayout>
</ScrollView>
</ContentPage.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,4 +217,9 @@ async void HandleModalPopupInCustomNavigationPage(object? sender, EventArgs even
var customNavigationPage = new NavigationPage(modalPopupPage);
await Shell.Current.Navigation.PushModalAsync(customNavigationPage, true);
}

async void HandleSoftInputKeyboardPopupClicked(object? sender, EventArgs eventArgs)
{
await popupService.ShowPopupAsync<SoftInputKeyboardPopup>(Navigation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8" ?>
<mct:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="CommunityToolkit.Maui.Sample.Views.Popups.SoftInputKeyboardPopup"
CanBeDismissedByTappingOutsideOfPopup="True">

<VerticalStackLayout Spacing="12">

<Label
Text="Keyboard for Entry"
FontSize="18"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
VerticalOptions="Center"
HorizontalOptions="Center"
FontAttributes="Bold" />

<Entry
Placeholder="Click here to enter text..."
TextColor="Black"
HorizontalTextAlignment="Start"
VerticalTextAlignment="Center"
VerticalOptions="Center"
HorizontalOptions="Center" />

<Label
x:Name="PickerForIOSLabel"
Text="Keyboard for Picker (iOS only)"
FontSize="18"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
VerticalOptions="Center"
HorizontalOptions="Center"
FontAttributes="Bold"
IsVisible="False" />

<Picker
x:Name="PickerForIOS"
Title="Select a monkey"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
VerticalOptions="Center"
HorizontalOptions="Center"
IsVisible="False">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>

<Label
x:Name="DatePickerForIOSLabel"
Text="Keyboard for DatePicker (iOS only)"
FontSize="18"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
VerticalOptions="Center"
HorizontalOptions="Center"
FontAttributes="Bold"
IsVisible="False" />

<DatePicker
x:Name="DatePickerForIOS"
MinimumDate="01/01/2020"
MaximumDate="12/31/2030"
Date="02/23/2026"
VerticalOptions="Center"
HorizontalOptions="Center"
IsVisible="False" />

<Button
Text="Close"
HorizontalOptions="Center"
VerticalOptions="Center"
Clicked="ClosePopup" />

</VerticalStackLayout>
</mct:Popup>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using CommunityToolkit.Maui.Views;

namespace CommunityToolkit.Maui.Sample.Views.Popups;

public partial class SoftInputKeyboardPopup : Popup
{
public SoftInputKeyboardPopup()
{
InitializeComponent();

#if IOS
PickerForIOSLabel.IsVisible = true;
PickerForIOS.IsVisible = true;
DatePickerForIOSLabel.IsVisible = true;
DatePickerForIOS.IsVisible = true;
#endif
}

async void ClosePopup(object? sender, EventArgs eventArgs)
{
await CloseAsync();
}
}
16 changes: 16 additions & 0 deletions src/CommunityToolkit.Maui/Views/Popup/Popup.android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;

namespace CommunityToolkit.Maui.Views;

public partial class Popup
{
partial void OnPlatformPopupOpened()
{
Microsoft.Maui.Controls.Application.Current?.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
}

partial void OnPlatformPopupClosed()
{
Microsoft.Maui.Controls.Application.Current?.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Unspecified);
}
}
82 changes: 82 additions & 0 deletions src/CommunityToolkit.Maui/Views/Popup/Popup.ios.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System.Diagnostics;
using Foundation;
using UIKit;

namespace CommunityToolkit.Maui.Views;

public partial class Popup
{
/// <summary>
/// Stores the keyboard will show notification observer to manage keyboard lifecycle.
/// </summary>
NSObject? willShow;

/// <summary>
/// Stores the keyboard will hide notification observer to manage keyboard lifecycle.
/// </summary>
NSObject? willHide;

/// <summary>
/// Stores the native platform view to adjust safe area insets when keyboard appears.
/// </summary>
UIView? popupNativeView;

/// <summary>
/// Stores the view controller associated with the popup to adjust safe area insets.
/// </summary>
UIViewController? viewController;

partial void OnPlatformPopupOpened()
{
if (Handler?.PlatformView is UIView view)
{
popupNativeView = view;
}

willShow = UIKeyboard.Notifications.ObserveWillShow((_, args) => HandleKeyboard(args));

willHide = UIKeyboard.Notifications.ObserveWillHide((_, args) => ResetSafeArea());
}

partial void OnPlatformPopupClosed()
{
willShow?.Dispose();
willHide?.Dispose();

willShow = willHide = null;

popupNativeView = null;
viewController = null;
}

/// <summary>
/// Adjusts the safe area insets when the keyboard appears on iOS.
/// </summary>
/// <param name="args">The keyboard event arguments containing the keyboard frame.</param>
void HandleKeyboard(UIKeyboardEventArgs args)
{
if (popupNativeView is null)
{
return;
}

viewController ??= popupNativeView.Window?.RootViewController?.PresentedViewController;

if (viewController is null)
{
Trace.WriteLine("Failed to retrieve the presented view controller.");

return;
}

viewController.AdditionalSafeAreaInsets = new UIEdgeInsets(0, 0, args.FrameEnd.Height, 0);
}

/// <summary>
/// Resets the safe area insets when the keyboard is hidden on iOS.
/// </summary>
void ResetSafeArea()
{
viewController?.AdditionalSafeAreaInsets = UIEdgeInsets.Zero;
}
}
10 changes: 9 additions & 1 deletion src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public Popup()
/// </remarks>
[BindableProperty]
public partial bool CanBeDismissedByTappingOutsideOfPopup { get; set; }

/// <summary>
/// Gets or sets the padding between the <see cref="Popup"/> border and the <see cref="Popup"/> content.
/// </summary>
Expand All @@ -74,11 +74,15 @@ public Popup()
internal void NotifyPopupIsOpened()
{
Opened?.Invoke(this, EventArgs.Empty);

OnPlatformPopupOpened();
}

internal void NotifyPopupIsClosed()
{
Closed?.Invoke(this, EventArgs.Empty);

OnPlatformPopupClosed();
}

private protected PopupPage GetPopupPage()
Expand All @@ -97,6 +101,10 @@ private protected PopupPage GetPopupPage()

throw new PopupNotFoundException();
}

partial void OnPlatformPopupOpened();

partial void OnPlatformPopupClosed();
}

/// <summary>
Expand Down
6 changes: 4 additions & 2 deletions src/CommunityToolkit.Maui/Views/Popup/PopupPage.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public PopupPage(Popup popup, IPopupOptions? popupOptions)
Shell.SetPresentationMode(this, PresentationMode.ModalNotAnimated);
On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.OverFullScreen);
NavigationPage.SetHasNavigationBar(this, false);

this.SafeAreaEdges = new SafeAreaEdges(SafeAreaRegions.Container, SafeAreaRegions.Container, SafeAreaRegions.Container, SafeAreaRegions.SoftInput);
}

public event EventHandler<IPopupResult>? PopupClosed;
Expand Down Expand Up @@ -221,7 +223,7 @@ public PopupPageLayout(in Popup popupContent, in IPopupOptions options, in Actio
Content = popupContent
};

// Bind `Popup` values through to Border using OneWay Bindings
// Bind `Popup` values through to Border using OneWay Bindings
PopupBorder.SetBinding(Border.MarginProperty, static (Popup popup) => popup.Margin, source: popupContent, mode: BindingMode.OneWay, converter: new MarginConverter());
PopupBorder.SetBinding(Border.BackgroundProperty, static (Popup popup) => popup.Background, source: popupContent, mode: BindingMode.OneWay);
PopupBorder.SetBinding(Border.BackgroundColorProperty, static (Popup popup) => popup.BackgroundColor, source: popupContent, mode: BindingMode.OneWay, converter: new BackgroundColorConverter());
Expand Down Expand Up @@ -254,7 +256,7 @@ void HandleOverlayTapped(object? sender, TappedEventArgs e)
return;
}

// Execute tapOutsideOfPopupCommand only if tap occurred outside the PopupBorder
// Execute tapOutsideOfPopupCommand only if tap occurred outside the PopupBorder
if (PopupBorder.Bounds.Contains(position.Value) is false)
{
tryExecuteTapOutsideOfPopupCommand();
Expand Down
Loading