Skip to content

Commit 553d284

Browse files
Add Popup.CanBeDismissedByTappingOutsideOfPopup
1 parent 6133ad1 commit 553d284

File tree

4 files changed

+76
-5
lines changed

4 files changed

+76
-5
lines changed

src/CommunityToolkit.Maui.UnitTests/Views/Popup/PopupPageTests.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using CommunityToolkit.Maui.Core;
22
using CommunityToolkit.Maui.Extensions;
3-
using CommunityToolkit.Maui.UnitTests.Extensions;
4-
using CommunityToolkit.Maui.UnitTests.Services;
53
using CommunityToolkit.Maui.Views;
64
using FluentAssertions;
75
using Microsoft.Maui.Controls.PlatformConfiguration;
@@ -219,6 +217,49 @@ public void PopupPageT_Close_ShouldThrowOperationCanceledException_WhenTokenIsCa
219217
act.Should().ThrowAsync<OperationCanceledException>();
220218
}
221219

220+
[Fact]
221+
public void TapGestureRecognizer_VerifyCanBeDismissedByTappingOutsideOfPopup_ShouldNotExecuteWhenEitherFalse()
222+
{
223+
// Arrange
224+
var view = new Popup
225+
{
226+
CanBeDismissedByTappingOutsideOfPopup = false
227+
};
228+
var popupOptions = new PopupOptions
229+
{
230+
CanBeDismissedByTappingOutsideOfPopup = false
231+
};
232+
233+
// Act
234+
var popupPage = new PopupPage(view, popupOptions);
235+
var tapGestureRecognizer = popupPage.Content.Children.OfType<BoxView>().Single().GestureRecognizers.OfType<TapGestureRecognizer>().Single();
236+
237+
// Assert
238+
Assert.False(tapGestureRecognizer.Command?.CanExecute(null));
239+
240+
// Act
241+
view.CanBeDismissedByTappingOutsideOfPopup = true;
242+
popupOptions.CanBeDismissedByTappingOutsideOfPopup = false;
243+
244+
// Assert
245+
Assert.False(tapGestureRecognizer.Command?.CanExecute(null));
246+
247+
// Act
248+
view.CanBeDismissedByTappingOutsideOfPopup = false;
249+
popupOptions.CanBeDismissedByTappingOutsideOfPopup = true;
250+
251+
// Assert
252+
Assert.False(tapGestureRecognizer.Command?.CanExecute(null));
253+
254+
// Act
255+
view.CanBeDismissedByTappingOutsideOfPopup = true;
256+
popupOptions.CanBeDismissedByTappingOutsideOfPopup = true;
257+
258+
// Assert
259+
Assert.True(tapGestureRecognizer.Command?.CanExecute(null));
260+
261+
}
262+
222263
[Fact]
223264
public void Constructor_WithViewAndPopupOptions_SetsCorrectProperties()
224265
{

src/CommunityToolkit.Maui/Primitives/Defaults/PopupDefaults.shared.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ static class PopupDefaults
3131
/// Default value for <see cref="VisualElement.BackgroundColor"/> BackgroundColor
3232
/// </summary>
3333
public static Color BackgroundColor { get; } = Colors.White;
34+
35+
/// <summary>
36+
/// Default value for <see cref="Popup.CanBeDismissedByTappingOutsideOfPopup"/>
37+
/// </summary>
38+
public const bool CanBeDismissedByTappingOutsideOfPopup = PopupOptionsDefaults.CanBeDismissedByTappingOutsideOfPopup;
3439
}

src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public partial class Popup : ContentView
2626
/// Bindable property to set the vertical position of the <see cref="Popup"/> when displayed on screen
2727
/// </summary>
2828
public static new readonly BindableProperty VerticalOptionsProperty = View.VerticalOptionsProperty;
29+
30+
/// <summary>
31+
/// Backing BindableProperty for the <see cref="CanBeDismissedByTappingOutsideOfPopup"/> property.
32+
/// </summary>
33+
public static readonly BindableProperty CanBeDismissedByTappingOutsideOfPopupProperty = BindableProperty.Create(nameof(CanBeDismissedByTappingOutsideOfPopup), typeof(bool), typeof(Popup), PopupDefaults.CanBeDismissedByTappingOutsideOfPopup);
2934

3035
/// <summary>
3136
/// Initializes Popup
@@ -83,6 +88,17 @@ public Popup()
8388
get => base.VerticalOptions;
8489
set => base.VerticalOptions = value;
8590
}
91+
92+
/// <inheritdoc cref="IPopupOptions.CanBeDismissedByTappingOutsideOfPopup"/> />
93+
/// <remarks>
94+
/// When true and the user taps outside the popup, it will dismiss.
95+
/// On Android - when false the hardware back button is disabled.
96+
/// </remarks>
97+
public bool CanBeDismissedByTappingOutsideOfPopup
98+
{
99+
get => (bool)GetValue(CanBeDismissedByTappingOutsideOfPopupProperty);
100+
set => SetValue(CanBeDismissedByTappingOutsideOfPopupProperty, value);
101+
}
86102

87103
/// <summary>
88104
/// Close the Popup.

src/CommunityToolkit.Maui/Views/Popup/PopupPage.shared.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ public PopupPage(Popup popup, IPopupOptions popupOptions)
4646
{
4747
popupOptions.OnTappingOutsideOfPopup?.Invoke();
4848
await CloseAsync(new PopupResult(true));
49-
}, () => popupOptions.CanBeDismissedByTappingOutsideOfPopup);
49+
}, () => popupOptions.CanBeDismissedByTappingOutsideOfPopup & popup.CanBeDismissedByTappingOutsideOfPopup);
5050

5151
// Only set the content if the parent constructor hasn't set the content already; don't override content if it already exists
5252
base.Content = new PopupPageLayout(popup, popupOptions, tapOutsideOfPopupCommand);
5353

54+
popup.PropertyChanged += HandlePopupPropertyChanged;
5455
if (popupOptions is BindableObject bindablePopupOptions)
5556
{
56-
bindablePopupOptions.PropertyChanged += HandlePopupPropertyChanged;
57+
bindablePopupOptions.PropertyChanged += HandlePopupOptionsPropertyChanged;
5758
}
5859

5960
this.SetBinding(BindingContextProperty, static (Popup x) => x.BindingContext, source: popup, mode: BindingMode.OneWay);
@@ -152,13 +153,21 @@ protected override void OnNavigatedTo(NavigatedToEventArgs args)
152153
return popup;
153154
}
154155

155-
void HandlePopupPropertyChanged(object? sender, PropertyChangedEventArgs e)
156+
void HandlePopupOptionsPropertyChanged(object? sender, PropertyChangedEventArgs e)
156157
{
157158
if (e.PropertyName == nameof(IPopupOptions.CanBeDismissedByTappingOutsideOfPopup))
158159
{
159160
tapOutsideOfPopupCommand.ChangeCanExecute();
160161
}
161162
}
163+
164+
void HandlePopupPropertyChanged(object? sender, PropertyChangedEventArgs e)
165+
{
166+
if (e.PropertyName == nameof(Popup.CanBeDismissedByTappingOutsideOfPopup))
167+
{
168+
tapOutsideOfPopupCommand.ChangeCanExecute();
169+
}
170+
}
162171

163172
void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query)
164173
{

0 commit comments

Comments
 (0)