diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/MainActivity.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/MainActivity.cs
index 9a00b8c733..0c945823c9 100644
--- a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/MainActivity.cs
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/MainActivity.cs
@@ -2,7 +2,6 @@
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
-using Xamarin.Essentials;
namespace Xamarin.CommunityToolkit.Sample.Droid
{
@@ -17,14 +16,15 @@ protected override void OnCreate(Bundle savedInstanceState)
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
- Platform.Init(this, savedInstanceState);
+ Essentials.Platform.Init(this, savedInstanceState);
+ ToolkitPlatform.Init(this);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
- Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+ Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj
index da7b065d51..05e317c65f 100644
--- a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample.Android/Xamarin.CommunityToolkit.Sample.Android.csproj
@@ -127,7 +127,7 @@
-
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml
new file mode 100644
index 0000000000..0229b4d1ef
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml.cs
new file mode 100644
index 0000000000..63fa5ecaf6
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/PopupGalleryPage.xaml.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views
+{
+ public partial class PopupGalleryPage
+ {
+ public PopupGalleryPage() => InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml
new file mode 100644
index 0000000000..c70ccdf886
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml.cs
new file mode 100644
index 0000000000..8c23d1d4d6
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ButtonPopup.xaml.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class ButtonPopup
+ {
+ public ButtonPopup() => InitializeComponent();
+
+ void Button_Clicked(object sender, System.EventArgs e) => Dismiss(null);
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml
new file mode 100644
index 0000000000..4bc1b5a866
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml.cs
new file mode 100644
index 0000000000..ca000ce338
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/MultipleButtonPopup.xaml.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class MultipleButtonPopup
+ {
+ public MultipleButtonPopup() => InitializeComponent();
+
+ void Cancel_Clicked(object sender, System.EventArgs e) => Dismiss(false);
+
+ void Okay_Clicked(object sender, System.EventArgs e) => Dismiss(true);
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml
new file mode 100644
index 0000000000..594ca398eb
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml.cs
new file mode 100644
index 0000000000..bbaff0d7d8
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/NoLightDismissPopup.xaml.cs
@@ -0,0 +1,9 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class NoLightDismissPopup
+ {
+ public NoLightDismissPopup() => InitializeComponent();
+
+ void Button_Clicked(object sender, System.EventArgs e) => Dismiss(null);
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml
new file mode 100644
index 0000000000..1ed70809c5
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml.cs
new file mode 100644
index 0000000000..92121fa121
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/OpenedEventSimplePopup.xaml.cs
@@ -0,0 +1,21 @@
+using Xamarin.CommunityToolkit.UI.Views;
+
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class OpenedEventSimplePopup
+ {
+ public OpenedEventSimplePopup()
+ {
+ InitializeComponent();
+ Opened += OnOpened;
+ }
+
+ void OnOpened(object sender, PopupOpenedEventArgs e)
+ {
+ Opened -= OnOpened;
+
+ title.Text = "Opened Event Popup";
+ message.Text = "The content of this popup was updated after the popup was rendered";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml
new file mode 100644
index 0000000000..05b6a1c0c9
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml.cs
new file mode 100644
index 0000000000..8aaf9728d6
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupAnchorPage.xaml.cs
@@ -0,0 +1,35 @@
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class PopupAnchorPage
+ {
+ public PopupAnchorPage() => InitializeComponent();
+
+ void OnPanUpdated(object sender, PanUpdatedEventArgs e)
+ {
+ if (sender is Label label)
+ {
+ if (Device.RuntimePlatform == Device.Android)
+ {
+ label.TranslationX += e.TotalX;
+ label.TranslationY += e.TotalY;
+ }
+ else
+ {
+ switch (e.StatusType)
+ {
+ case GestureStatus.Running:
+ label.TranslationX = e.TotalX;
+ label.TranslationY = e.TotalY;
+ break;
+ case GestureStatus.Completed:
+ label.TranslationX += e.TotalX;
+ label.TranslationY += e.TotalY;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml
new file mode 100644
index 0000000000..bf69cf869d
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml.cs
new file mode 100644
index 0000000000..090c7d20bd
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/PopupPositionPage.xaml.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class PopupPositionPage
+ {
+ public PopupPositionPage() => InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml
new file mode 100644
index 0000000000..6905a52062
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml.cs
new file mode 100644
index 0000000000..0adc37d6aa
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/SimplePopup.xaml.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class SimplePopup
+ {
+ public SimplePopup() => InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml
new file mode 100644
index 0000000000..5c6e657f53
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml.cs
new file mode 100644
index 0000000000..a4c34429c9
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/ToggleSizePopup.xaml.cs
@@ -0,0 +1,27 @@
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class ToggleSizePopup
+ {
+ Size originalSize;
+
+ public ToggleSizePopup()
+ {
+ InitializeComponent();
+ originalSize = Size;
+ }
+
+ void Button_Clicked(object sender, System.EventArgs e)
+ {
+ if (originalSize == Size)
+ {
+ Size = new Size(originalSize.Width * 1.25, originalSize.Height * 1.25);
+ }
+ else
+ {
+ Size = originalSize;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml
new file mode 100644
index 0000000000..edf9d56266
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml.cs
new file mode 100644
index 0000000000..c260895a6c
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Pages/Views/Popups/TransparentPopup.xaml.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.CommunityToolkit.Sample.Pages.Views.Popups
+{
+ public partial class TransparentPopup
+ {
+ public TransparentPopup() => InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/PopupControlViewModel.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/PopupControlViewModel.cs
new file mode 100644
index 0000000000..0c71bfaabe
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/PopupControlViewModel.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Input;
+using Xamarin.CommunityToolkit.Extensions;
+using Xamarin.CommunityToolkit.Sample.Models;
+using Xamarin.CommunityToolkit.Sample.Pages.Views.Popups;
+using Xamarin.CommunityToolkit.UI.Views;
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.ViewModels.Views
+{
+ public class PopupControlViewModel
+ {
+ INavigation Navigation => App.Current.MainPage.Navigation;
+
+ public IEnumerable Examples { get; } = new List {
+ new SectionModel(typeof(SimplePopup), "Simple Popup", Color.Red, "Displays a basic popup centered on the screen"),
+ new SectionModel(typeof(PopupPositionPage), "Custom Positioning Popup", Color.Red, "Displays a basic popup anywhere on the screen using VerticalOptions and HorizontalOptions"),
+ new SectionModel(typeof(ButtonPopup), "Popup With 1 Button", Color.Red, "Displays a basic popup with a confirm button"),
+ new SectionModel(typeof(MultipleButtonPopup), "Popup With Multiple Buttons", Color.Red, "Displays a basic popup with a cancel and confirm button"),
+ new SectionModel(typeof(NoLightDismissPopup), "Simple Popup Without Light Dismiss", Color.Red, "Displays a basic popup but does not allow the user to close it if they tap outside of the popup. In other words the LightDismiss is set to false."),
+ new SectionModel(typeof(ToggleSizePopup), "Toggle Size Popup", Color.Red, "Displays a popup that can have it's size updated by pressing a button"),
+ new SectionModel(typeof(TransparentPopup), "Transparent Popup", Color.Red, "Displays a popup with a transparent background"),
+ new SectionModel(typeof(PopupAnchorPage), "Anchor Popup", Color.Red, "Popups can be anchored to other view's on the screen"),
+ new SectionModel(typeof(OpenedEventSimplePopup), "Opened Event Popup", Color.Red, "Popup with opened event"),
+ };
+
+ public ICommand DisplayPopup => new Command(OnDisplayPopup);
+
+ void OnDisplayPopup(Type popupType)
+ {
+ var view = (VisualElement)Activator.CreateInstance(popupType);
+ if (view is BasePopup popup)
+ {
+ Navigation.ShowPopup(popup);
+ }
+ else if (view is Page page)
+ {
+ Navigation.PushAsync(page);
+ }
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupAnchorViewModel.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupAnchorViewModel.cs
new file mode 100644
index 0000000000..375da6cf49
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupAnchorViewModel.cs
@@ -0,0 +1,21 @@
+using System.Windows.Input;
+using Xamarin.CommunityToolkit.Extensions;
+using Xamarin.CommunityToolkit.Sample.Pages.Views.Popups;
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.ViewModels.Views.Popups
+{
+ public class PopupAnchorViewModel
+ {
+ INavigation Navigation => App.Current.MainPage.Navigation;
+
+ public ICommand ShowPopup => new Command(OnShowPopup);
+
+ void OnShowPopup(View anchor)
+ {
+ var popup = new TransparentPopup();
+ popup.Anchor = anchor;
+ Navigation.ShowPopup(popup);
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupPositionViewModel.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupPositionViewModel.cs
new file mode 100644
index 0000000000..517365ace1
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/Popups/PopupPositionViewModel.cs
@@ -0,0 +1,74 @@
+using System.Windows.Input;
+using Xamarin.CommunityToolkit.Extensions;
+using Xamarin.CommunityToolkit.Sample.Pages.Views.Popups;
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Sample.ViewModels.Views.Popups
+{
+ public class PopupPositionViewModel
+ {
+ INavigation Navigation => App.Current.MainPage.Navigation;
+
+ public ICommand DisplayPopup => new Command(OnDisplayPopup);
+
+ void OnDisplayPopup(PopupPosition position)
+ {
+ var popup = new SimplePopup();
+
+ switch (position)
+ {
+ case PopupPosition.TopLeft:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ break;
+ case PopupPosition.Top:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ break;
+ case PopupPosition.TopRight:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ break;
+ case PopupPosition.Left:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ break;
+ case PopupPosition.Center:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ break;
+ case PopupPosition.Right:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ break;
+ case PopupPosition.BottomLeft:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Start, true);
+ break;
+ case PopupPosition.Bottom:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.Center, true);
+ break;
+ case PopupPosition.BottomRight:
+ popup.VerticalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.End, true);
+ break;
+ }
+
+ Navigation.ShowPopup(popup);
+ }
+
+ public enum PopupPosition
+ {
+ TopLeft = 0,
+ Top = 1,
+ TopRight = 2,
+ Left = 3,
+ Center = 4,
+ Right = 5,
+ BottomLeft = 6,
+ Bottom = 7,
+ BottomRight = 8
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/ViewsGalleryViewModel.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
index 26dd7d0dc0..1a1bc370d4 100644
--- a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
@@ -48,7 +48,10 @@ public class ViewsGalleryViewModel : BaseGalleryViewModel
"A control to display a set of tabs and their respective content."),
new SectionModel(typeof(UniformGridPage), "UniformGrid",
- "The UniformGrid is just like the Grid, with all rows and columns will have the same size.")
+ "The UniformGrid is just like the Grid, with all rows and columns will have the same size."),
+
+ new SectionModel(typeof(PopupGalleryPage), "Popup",
+ "The popup control renders native popups from the shared code. This page demonstrates a variety of different techniques for displaying native popups.")
};
}
}
\ No newline at end of file
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Xamarin.CommunityToolkit.Sample.csproj b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Xamarin.CommunityToolkit.Sample.csproj
index 9793d34f6d..a74356ce80 100644
--- a/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Xamarin.CommunityToolkit.Sample.csproj
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit.Sample/Xamarin.CommunityToolkit.Sample.csproj
@@ -12,6 +12,7 @@
+
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.android.cs
new file mode 100644
index 0000000000..c9fd831cc7
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.android.cs
@@ -0,0 +1,13 @@
+using Xamarin.CommunityToolkit.UI.Views;
+using Xamarin.Forms.Platform.Android;
+
+namespace Xamarin.CommunityToolkit.Extensions
+{
+ public static partial class NavigationExtensions
+ {
+ static void OnShowPopup(BasePopup popup)
+ {
+ Platform.CreateRendererWithContext(popup, ToolkitPlatform.Context);
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.ios.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.ios.cs
new file mode 100644
index 0000000000..463a19d13d
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.ios.cs
@@ -0,0 +1,13 @@
+using Xamarin.CommunityToolkit.UI.Views;
+using Xamarin.Forms.Platform.iOS;
+
+namespace Xamarin.CommunityToolkit.Extensions
+{
+ public static partial class NavigationExtensions
+ {
+ static void OnShowPopup(BasePopup popup)
+ {
+ Platform.CreateRenderer(popup);
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.shared.cs
new file mode 100644
index 0000000000..766016e14e
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.shared.cs
@@ -0,0 +1,34 @@
+using System;
+using Xamarin.CommunityToolkit.UI.Views;
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.Extensions
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static partial class NavigationExtensions
+ {
+ ///
+ /// Displays a popup.
+ ///
+ ///
+ /// The current .
+ ///
+ ///
+ /// The to display.
+ ///
+ public static void ShowPopup(this INavigation navigation, BasePopup popup)
+ {
+#if __ANDROID__
+ OnShowPopup(popup);
+#elif __IOS__
+ OnShowPopup(popup);
+#elif WINDOWS_UWP
+ OnShowPopup(popup);
+#else
+ throw new NotSupportedException($"The current platform '{Device.RuntimePlatform}' does not support Xamarin Community Toolkit Popups.");
+#endif
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs
new file mode 100644
index 0000000000..e15ac44b47
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/Navigation/NavigationExtensions.uwp.cs
@@ -0,0 +1,33 @@
+using System.Linq;
+using Xamarin.CommunityToolkit.UI.Views;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.UWP;
+
+namespace Xamarin.CommunityToolkit.Extensions
+{
+ public static partial class NavigationExtensions
+ {
+ static void OnShowPopup(BasePopup popup)
+ {
+ popup.Parent = GetCurrentPage(Application.Current.MainPage);
+ Platform.CreateRenderer(popup);
+
+ // https://github.com/xamarin/Xamarin.Forms/blob/0c95d0976cc089fe72476fb037851a64987de83c/Xamarin.Forms.Platform.iOS/PageExtensions.cs#L44
+ Page GetCurrentPage(Page currentPage)
+ {
+ if (currentPage.NavigationProxy.ModalStack.LastOrDefault() is Page modal)
+ return modal;
+ else if (currentPage is MasterDetailPage mdp)
+ return GetCurrentPage(mdp.Detail);
+ else if (currentPage is FlyoutPage fp)
+ return GetCurrentPage(fp.Detail);
+ else if (currentPage is Shell shell && shell.CurrentItem?.CurrentItem is IShellSectionController ssc)
+ return ssc.PresentedPage;
+ else if (currentPage is IPageContainer pc)
+ return GetCurrentPage(pc.CurrentPage);
+ else
+ return currentPage;
+ }
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElementExtension.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtension.shared.cs
similarity index 91%
rename from src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElementExtension.shared.cs
rename to src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtension.shared.cs
index d7f4f9249f..8906ec0309 100644
--- a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElementExtension.shared.cs
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtension.shared.cs
@@ -3,7 +3,10 @@
namespace Xamarin.CommunityToolkit.Extensions
{
- public static class VisualElementExtension
+ ///
+ /// Extension methods for .
+ ///
+ public static partial class VisualElementExtension
{
public static Task ColorTo(this VisualElement element, Color color, uint length = 250u, Easing easing = null)
{
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtensions.uwp.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtensions.uwp.cs
new file mode 100644
index 0000000000..53ddcc1b09
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Extensions/VisualElement/VisualElementExtensions.uwp.cs
@@ -0,0 +1,51 @@
+using System;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.UWP;
+
+namespace Xamarin.CommunityToolkit.Extensions
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static partial class VisualElementExtensions
+ {
+
+ ///
+ /// cleanup object to dispose and
+ /// destroy resources.
+ ///
+ ///
+ /// The to cleanup.
+ ///
+ ///
+ /// This extension method is ported from Xamarin.Forms and should remain in sync.
+ ///
+ internal static void Cleanup(this VisualElement self)
+ {
+ if (self == null)
+ throw new ArgumentNullException("self");
+
+ var renderer = Platform.GetRenderer(self);
+
+ foreach (var element in self.Descendants())
+ {
+ var visual = element as VisualElement;
+ if (visual == null)
+ continue;
+
+ var childRenderer = Platform.GetRenderer(visual);
+ if (childRenderer != null)
+ {
+ childRenderer.Dispose();
+ Platform.SetRenderer(visual, null);
+ }
+ }
+
+ if (renderer != null)
+ {
+ renderer.Dispose();
+ Platform.SetRenderer(self, null);
+ }
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/FormsToolkit.ios.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/FormsToolkit.ios.cs
new file mode 100644
index 0000000000..c515b44d71
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Helpers/FormsToolkit.ios.cs
@@ -0,0 +1,20 @@
+using UIKit;
+
+namespace Xamarin.CommunityToolkit.Helpers
+{
+ public static class FormsToolkit
+ {
+ static bool? isiOS9OrNewer;
+
+ public static bool IsiOS9OrNewer
+ {
+ get
+ {
+ if (!isiOS9OrNewer.HasValue)
+ isiOS9OrNewer = UIDevice.CurrentDevice.CheckSystemVersion(9, 0);
+
+ return isiOS9OrNewer.Value;
+ }
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs
new file mode 100644
index 0000000000..c2db788822
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Startup/ToolkitPlatform.android.cs
@@ -0,0 +1,26 @@
+using Android.Content;
+
+namespace Xamarin.CommunityToolkit
+{
+ ///
+ /// Platform extension methods.
+ ///
+ public static partial class ToolkitPlatform
+ {
+ ///
+ /// Gets the .
+ ///
+ internal static Context Context { get; private set; }
+
+ ///
+ /// Initializes the Android .
+ ///
+ ///
+ /// The current .
+ ///
+ public static void Init(Context context)
+ {
+ Context = context;
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/BasePopup.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/BasePopup.shared.cs
new file mode 100644
index 0000000000..b9f290c9bb
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/BasePopup.shared.cs
@@ -0,0 +1,175 @@
+using System;
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.UI.Views
+{
+ ///
+ /// The popup controls base implementation.
+ ///
+ public abstract class BasePopup : VisualElement
+ {
+ ///
+ /// Instantiates a new instance of .
+ ///
+ public BasePopup()
+ {
+ Color = Color.White;
+ BorderColor = default(Color);
+ VerticalOptions = LayoutOptions.CenterAndExpand;
+ HorizontalOptions = LayoutOptions.CenterAndExpand;
+ IsLightDismissEnabled = true;
+ }
+
+ public static BindableProperty ColorProperty = BindableProperty.Create(nameof(Color), typeof(Color), typeof(BasePopup));
+ public static BindableProperty SizeProperty = BindableProperty.Create(nameof(Size), typeof(Size), typeof(BasePopup));
+
+ public static BindableProperty VerticalOptionsProperty = BindableProperty.Create(nameof(VerticalOptions), typeof(LayoutOptions), typeof(BasePopup), LayoutOptions.CenterAndExpand);
+ public static BindableProperty HorizontalOptionsProperty = BindableProperty.Create(nameof(HorizontalOptions), typeof(LayoutOptions), typeof(BasePopup), LayoutOptions.CenterAndExpand);
+
+ ///
+ /// Gets or sets the to render in the Popup.
+ ///
+ ///
+ /// The View can be or type: , or
+ ///
+ public virtual View View { get; set; }
+
+ ///
+ /// Gets or sets the of the Popup.
+ ///
+ ///
+ /// This color sets the native background color of the , which is
+ /// independent of any background color configured in the actual View.
+ ///
+ public Color Color
+ {
+ get => (Color)GetValue(ColorProperty);
+ set => SetValue(ColorProperty, value);
+ }
+
+ ///
+ /// Gets or sets the for positioning the vertically on the screen.
+ ///
+ public LayoutOptions VerticalOptions
+ {
+ get => (LayoutOptions)GetValue(VerticalOptionsProperty);
+ set => SetValue(VerticalOptionsProperty, value);
+ }
+
+ ///
+ /// Gets or sets the for positioning the horizontally on the screen.
+ ///
+ public LayoutOptions HorizontalOptions
+ {
+ get => (LayoutOptions)GetValue(HorizontalOptionsProperty);
+ set => SetValue(HorizontalOptionsProperty, value);
+ }
+
+ // REVIEW - 11/30/2020 - ahoefling
+ // In the original code review https://github.com/xamarin/Xamarin.Forms/pull/9616
+ // It was recommended to configure BorderColor as a platform specific attached
+ // property since it is only usable on UWP.
+ //
+ // Do we want to leave this as part of the API with plans to implement or
+ // should we move it as an attached property.
+
+ ///
+ /// Gets or sets the of the Popup Border.
+ ///
+ ///
+ /// This color sets the native border color of the , which is
+ /// independent of any border color configured in the actual view.
+ ///
+ public Color BorderColor { get; set; } // UWP ONLY - wasn't originally in spec
+
+ ///
+ /// Gets or sets the anchor.
+ ///
+ ///
+ /// The Anchor is where the Popup will render closest to. When an Anchor is configured
+ /// the popup will appear centered over that control or as close as possible.
+ ///
+ public View Anchor { get; set; }
+
+ ///
+ /// Gets or sets the of the Popup Display.
+ ///
+ ///
+ /// The Popup will always try to constrain the actual size of the
+ /// to the of the View unless a is specified.
+ /// If the contiains a
+ /// will be required. This will allow the View to have a concept of
+ /// that varies from the actual of the
+ ///
+ public Size Size
+ {
+ get => (Size)GetValue(SizeProperty);
+ set => SetValue(SizeProperty, value);
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the popup can be light dismissed.
+ ///
+ ///
+ /// When true and the user taps outside of the popup it will dismiss.
+ ///
+ public bool IsLightDismissEnabled { get; set; }
+
+ ///
+ /// Dismissed event is invoked when the popup is closed.
+ ///
+ public event EventHandler Dismissed;
+
+ ///
+ /// Opened event is invoked when the popup is opened.
+ ///
+ public event EventHandler Opened;
+
+ ///
+ /// Invokes the event.
+ ///
+ ///
+ /// The results to add to the .
+ ///
+ protected void OnDismissed(object result)
+ {
+ Dismissed?.Invoke(this, new PopupDismissedEventArgs { Result = result });
+ }
+
+ ///
+ /// Invokes the event.
+ ///
+ internal virtual void OnOpened()
+ {
+ Opened?.Invoke(this, new PopupOpenedEventArgs());
+ }
+
+ ///
+ /// Invoked when the popup is light dismissed. In other words when the
+ /// user taps outside of the popup and it closes.
+ ///
+ public virtual void LightDismiss()
+ {
+ // REVIEW - AH 12/3/2020
+ // Should this API be protected internal? It is not intended
+ // to be called outside of XCT, but it should allow for subclassing.
+
+ // TODO - AH 12/3/2020
+ // This is not being tested correctly. It is not
+ // implemented in iOS or UWP.
+
+ // empty default implementation
+ }
+
+ ///
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ if (View != null)
+ {
+ SetInheritedBindingContext(View, BindingContext);
+ }
+ }
+ }
+}
diff --git a/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Popup.shared.cs b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Popup.shared.cs
new file mode 100644
index 0000000000..e7717d8ab1
--- /dev/null
+++ b/src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Popup/Popup.shared.cs
@@ -0,0 +1,27 @@
+using Xamarin.Forms;
+
+namespace Xamarin.CommunityToolkit.UI.Views
+{
+ ///
+ /// Default popup implementation that uses a
+ /// generic result.
+ ///
+ public class Popup : Popup