|
1 | 1 | using System.ComponentModel; |
2 | 2 | using System.Globalization; |
| 3 | +using System.Windows.Input; |
3 | 4 | using CommunityToolkit.Maui.Converters; |
4 | 5 | using CommunityToolkit.Maui.Core; |
5 | 6 | using CommunityToolkit.Maui.Extensions; |
@@ -41,16 +42,14 @@ public PopupPage(Popup popup, IPopupOptions popupOptions) |
41 | 42 | this.popup = popup; |
42 | 43 | this.popupOptions = popupOptions; |
43 | 44 |
|
44 | | - // Only set the content if the parent constructor hasn't set the content already; don't override content if it already exists |
45 | | - base.Content ??= new PopupPageLayout(popup, popupOptions); |
46 | | - |
47 | 45 | tapOutsideOfPopupCommand = new Command(async () => |
48 | 46 | { |
49 | 47 | popupOptions.OnTappingOutsideOfPopup?.Invoke(); |
50 | 48 | await CloseAsync(new PopupResult(true)); |
51 | 49 | }, () => popupOptions.CanBeDismissedByTappingOutsideOfPopup); |
52 | 50 |
|
53 | | - Content.GestureRecognizers.Add(new TapGestureRecognizer { Command = tapOutsideOfPopupCommand }); |
| 51 | + // Only set the content if the parent constructor hasn't set the content already; don't override content if it already exists |
| 52 | + base.Content = new PopupPageLayout(popup, popupOptions, tapOutsideOfPopupCommand); |
54 | 53 |
|
55 | 54 | if (popupOptions is BindableObject bindablePopupOptions) |
56 | 55 | { |
@@ -104,15 +103,15 @@ public async Task CloseAsync(PopupResult result, CancellationToken token = defau |
104 | 103 |
|
105 | 104 | popupClosedEventManager.HandleEvent(this, result, nameof(PopupClosed)); |
106 | 105 | } |
107 | | - |
| 106 | + |
108 | 107 | protected override bool OnBackButtonPressed() |
109 | 108 | { |
110 | 109 | // Only close the Popup if PopupOptions.CanBeDismissedByTappingOutsideOfPopup is true |
111 | 110 | if (popupOptions.CanBeDismissedByTappingOutsideOfPopup) |
112 | 111 | { |
113 | 112 | CloseAsync(new PopupResult(true), CancellationToken.None).SafeFireAndForget(); |
114 | 113 | } |
115 | | - |
| 114 | + |
116 | 115 | // Always return true to let the Android Operating System know that we are manually handling the Navigation request from the Android Back Button |
117 | 116 | return true; |
118 | 117 | } |
@@ -176,33 +175,44 @@ void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query) |
176 | 175 |
|
177 | 176 | internal sealed partial class PopupPageLayout : Grid |
178 | 177 | { |
179 | | - public PopupPageLayout(in Popup popupContent, in IPopupOptions options) |
| 178 | + public PopupPageLayout(in Popup popupContent, in IPopupOptions options, in ICommand tapOutsideOfPopupCommand) |
180 | 179 | { |
181 | 180 | Background = BackgroundColor = null; |
182 | 181 |
|
183 | | - var border = new Border |
| 182 | + var tappableBackground = new BoxView |
| 183 | + { |
| 184 | + BackgroundColor = Colors.Transparent, |
| 185 | + HorizontalOptions = LayoutOptions.Fill, |
| 186 | + VerticalOptions = LayoutOptions.Fill |
| 187 | + }; |
| 188 | + tappableBackground.GestureRecognizers.Add(new TapGestureRecognizer { Command = tapOutsideOfPopupCommand }); |
| 189 | + Children.Add(tappableBackground); // Add the Tappable Background to the PopupPageLayout Grid before adding the Border to ensure the Border is displayed on top |
| 190 | + |
| 191 | + PopupBorder = new Border |
184 | 192 | { |
185 | 193 | BackgroundColor = popupContent.BackgroundColor ??= PopupDefaults.BackgroundColor, |
186 | 194 | Content = popupContent |
187 | 195 | }; |
188 | 196 |
|
189 | 197 | // Bind `Popup` values through to Border using OneWay Bindings |
190 | | - border.SetBinding(Border.MarginProperty, static (Popup popup) => popup.Margin, source: popupContent, mode: BindingMode.OneWay); |
191 | | - border.SetBinding(Border.PaddingProperty, static (Popup popup) => popup.Padding, source: popupContent, mode: BindingMode.OneWay); |
192 | | - border.SetBinding(Border.BackgroundProperty, static (Popup popup) => popup.Background, source: popupContent, mode: BindingMode.OneWay); |
193 | | - border.SetBinding(Border.BackgroundColorProperty, static (Popup popup) => popup.BackgroundColor, source: popupContent, mode: BindingMode.OneWay); |
194 | | - border.SetBinding(Border.VerticalOptionsProperty, static (Popup popup) => popup.VerticalOptions, source: popupContent, mode: BindingMode.OneWay); |
195 | | - border.SetBinding(Border.HorizontalOptionsProperty, static (Popup popup) => popup.HorizontalOptions, source: popupContent, mode: BindingMode.OneWay); |
| 198 | + PopupBorder.SetBinding(Border.MarginProperty, static (Popup popup) => popup.Margin, source: popupContent, mode: BindingMode.OneWay); |
| 199 | + PopupBorder.SetBinding(Border.PaddingProperty, static (Popup popup) => popup.Padding, source: popupContent, mode: BindingMode.OneWay); |
| 200 | + PopupBorder.SetBinding(Border.BackgroundProperty, static (Popup popup) => popup.Background, source: popupContent, mode: BindingMode.OneWay); |
| 201 | + PopupBorder.SetBinding(Border.BackgroundColorProperty, static (Popup popup) => popup.BackgroundColor, source: popupContent, mode: BindingMode.OneWay); |
| 202 | + PopupBorder.SetBinding(Border.VerticalOptionsProperty, static (Popup popup) => popup.VerticalOptions, source: popupContent, mode: BindingMode.OneWay); |
| 203 | + PopupBorder.SetBinding(Border.HorizontalOptionsProperty, static (Popup popup) => popup.HorizontalOptions, source: popupContent, mode: BindingMode.OneWay); |
196 | 204 |
|
197 | 205 | // Bind `PopupOptions` values through to Border using OneWay Bindings |
198 | | - border.SetBinding(Border.ShadowProperty, static (IPopupOptions options) => options.Shadow, source: options, mode: BindingMode.OneWay); |
199 | | - border.SetBinding(Border.StrokeProperty, static (IPopupOptions options) => options.Shape, source: options, converter: new BorderStrokeConverter(), mode: BindingMode.OneWay); |
200 | | - border.SetBinding(Border.StrokeShapeProperty, static (IPopupOptions options) => options.Shape, source: options, mode: BindingMode.OneWay); |
201 | | - border.SetBinding(Border.StrokeThicknessProperty, static (IPopupOptions options) => options.Shape, source: options, converter: new BorderStrokeThicknessConverter(), mode: BindingMode.OneWay); |
| 206 | + PopupBorder.SetBinding(Border.ShadowProperty, static (IPopupOptions options) => options.Shadow, source: options, mode: BindingMode.OneWay); |
| 207 | + PopupBorder.SetBinding(Border.StrokeProperty, static (IPopupOptions options) => options.Shape, source: options, converter: new BorderStrokeConverter(), mode: BindingMode.OneWay); |
| 208 | + PopupBorder.SetBinding(Border.StrokeShapeProperty, static (IPopupOptions options) => options.Shape, source: options, mode: BindingMode.OneWay); |
| 209 | + PopupBorder.SetBinding(Border.StrokeThicknessProperty, static (IPopupOptions options) => options.Shape, source: options, converter: new BorderStrokeThicknessConverter(), mode: BindingMode.OneWay); |
202 | 210 |
|
203 | | - Children.Add(border); |
| 211 | + Children.Add(PopupBorder); |
204 | 212 | } |
205 | 213 |
|
| 214 | + public Border PopupBorder { get; } |
| 215 | + |
206 | 216 | sealed partial class BorderStrokeThicknessConverter : BaseConverterOneWay<Shape?, double> |
207 | 217 | { |
208 | 218 | public override double DefaultConvertReturnValue { get; set; } = PopupOptionsDefaults.BorderStrokeThickness; |
|
0 commit comments