Skip to content

Commit 8ef1f6a

Browse files
Merge pull request #235 from syncfusion/BottomSheetOverlayVisibility
[Android] SfBottomSheet backdrop overlay remains visible after dismissal, blocking touch interaction
2 parents 9255830 + 2ad76c5 commit 8ef1f6a

File tree

2 files changed

+121
-70
lines changed

2 files changed

+121
-70
lines changed

maui/src/BottomSheet/SfBottomSheet.cs

Lines changed: 114 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.Maui.Controls.Shapes;
1+
using Microsoft.Maui.Controls.Shapes;
22
using Syncfusion.Maui.Toolkit.Internals;
33
using Syncfusion.Maui.Toolkit.Themes;
44
using Syncfusion.Maui.Toolkit.Helper;
@@ -74,11 +74,16 @@ public partial class SfBottomSheet : SfView, IParentThemeElement
7474
/// </summary>
7575
bool _isPointerPressed;
7676

77-
// Touch tracking
78-
/// <summary>
79-
/// The initial Y-coordinate of a touch event on the bottom sheet.
80-
/// </summary>
81-
double _initialTouchY;
77+
/// <summary>
78+
/// Indicates whether the overlay grid is currently added to the view hierarchy.
79+
/// </summary>
80+
bool _isOverlayAdded;
81+
82+
// Touch tracking
83+
/// <summary>
84+
/// The initial Y-coordinate of a touch event on the bottom sheet.
85+
/// </summary>
86+
double _initialTouchY;
8287

8388
/// <summary>
8489
/// The starting Y-coordinate of a swipe gesture on the bottom sheet.
@@ -1242,7 +1247,7 @@ internal Color OverlayBackgroundColor
12421247
/// </exception>
12431248
public void Show()
12441249
{
1245-
if (_bottomSheet is null || _overlayGrid is null)
1250+
if (_bottomSheet is null)
12461251
{
12471252
return;
12481253
}
@@ -1267,15 +1272,15 @@ public void Show()
12671272
/// </exception>
12681273
public void Close()
12691274
{
1270-
if(_bottomSheet is null || _overlayGrid is null)
1275+
if(_bottomSheet is null)
12711276
{
12721277
return;
12731278
}
12741279

12751280
AnimateBottomSheet(Height, onFinish: () =>
12761281
{
12771282
_bottomSheet.IsVisible = false;
1278-
_overlayGrid.IsVisible = false;
1283+
RemoveOverlayFromView();
12791284
});
12801285

12811286
if (_isSheetOpen)
@@ -1356,9 +1361,8 @@ void InitializeLayout()
13561361
InitializeBottomSheetBorder();
13571362
InitializeContentBorder();
13581363

1359-
if (_bottomSheet is not null && _overlayGrid is not null)
1364+
if (_bottomSheet is not null)
13601365
{
1361-
Children.Add(_overlayGrid);
13621366
Children.Add(_bottomSheet);
13631367
_bottomSheet.IsVisible = false;
13641368
}
@@ -1370,6 +1374,7 @@ void InitializeLayout()
13701374
void UpdateContentView()
13711375
{
13721376
Children.Clear();
1377+
_isOverlayAdded = false; // Reset overlay state
13731378
UpdateAllChild();
13741379
}
13751380

@@ -1379,7 +1384,6 @@ void UpdateContentView()
13791384
void UpdateAllChild()
13801385
{
13811386
AddChild(Content);
1382-
AddChild(_overlayGrid);
13831387
AddChild(_bottomSheet);
13841388
}
13851389

@@ -1404,7 +1408,7 @@ void InitializeOverlayGrid()
14041408
{
14051409
BackgroundColor = OverlayBackgroundColor,
14061410
Opacity = DefaultOverlayOpacity,
1407-
IsVisible = false
1411+
IsVisible = true
14081412
};
14091413

14101414
var tapGestureRecognizer = new TapGestureRecognizer();
@@ -1485,6 +1489,36 @@ void InitializeBottomSheetBorder()
14851489
};
14861490
}
14871491

1492+
/// <summary>
1493+
/// Adds the overlay grid to the view hierarchy if it's not already added and modal is enabled.
1494+
/// </summary>
1495+
void AddOverlayToView()
1496+
{
1497+
if (_overlayGrid is not null && IsModal && !_isOverlayAdded)
1498+
{
1499+
if (!Children.Contains(_overlayGrid))
1500+
{
1501+
Children.Insert(Children.Count - 1, _overlayGrid); // Insert before bottom sheet
1502+
}
1503+
_isOverlayAdded = true;
1504+
}
1505+
}
1506+
1507+
/// <summary>
1508+
/// Removes the overlay grid from the view hierarchy.
1509+
/// </summary>
1510+
void RemoveOverlayFromView()
1511+
{
1512+
if (_overlayGrid is not null && _isOverlayAdded)
1513+
{
1514+
if (Children.Contains(_overlayGrid))
1515+
{
1516+
Children.Remove(_overlayGrid);
1517+
}
1518+
_isOverlayAdded = false;
1519+
}
1520+
}
1521+
14881522
/// <summary>
14891523
/// Calculates the initial height for the half-expanded state.
14901524
/// </summary>
@@ -2040,16 +2074,20 @@ void RegisterSizeChangedEvent()
20402074
/// </summary>
20412075
void SetupBottomSheetForShow()
20422076
{
2043-
if (_isSheetOpen || _bottomSheet is null || _overlayGrid is null)
2077+
if (_isSheetOpen || _bottomSheet is null)
20442078
{
20452079
return;
20462080
}
20472081

20482082
// Position the bottom sheet just below the visible area
20492083
_bottomSheet.TranslationY = Height;
20502084
_bottomSheet.IsVisible = true;
2051-
_overlayGrid.IsVisible = IsModal;
2052-
_overlayGrid.Opacity = 0;
2085+
2086+
// Add overlay to view if modal
2087+
if (IsModal)
2088+
{
2089+
AddOverlayToView();
2090+
}
20532091
}
20542092

20552093

@@ -2133,11 +2171,6 @@ void AnimateBottomSheet(double targetPosition, Action? onFinish = null)
21332171
_bottomSheet.AbortAnimation("bottomSheetAnimation");
21342172
}
21352173

2136-
if (_overlayGrid.AnimationIsRunning("overlayGridAnimation"))
2137-
{
2138-
_overlayGrid.AbortAnimation("overlayGridAnimation");
2139-
}
2140-
21412174
int animationDuration = this.GetClampedAnimationDuration();
21422175
const int topPadding = 2;
21432176
_isSheetOpen = true;
@@ -2159,46 +2192,45 @@ void AnimateBottomSheet(double targetPosition, Action? onFinish = null)
21592192
/// </summary>
21602193
void AnimateOverlay(int animationDuration)
21612194
{
2162-
if (_overlayGrid is not null)
2195+
if (_overlayGrid is null || !IsModal)
21632196
{
2164-
double startValue = 0;
2165-
double endValue = 0;
2166-
_overlayGrid.IsVisible = IsModal;
2197+
return;
2198+
}
21672199

2168-
if (IsModal)
2200+
// Ensure overlay is added to view when needed
2201+
bool shouldShowOverlay = State is not (BottomSheetState.Collapsed or BottomSheetState.Hidden);
2202+
2203+
if (shouldShowOverlay)
2204+
{
2205+
AddOverlayToView();
2206+
}
2207+
2208+
if (_overlayGrid.AnimationIsRunning("overlayGridAnimation"))
2209+
{
2210+
_overlayGrid.AbortAnimation("overlayGridAnimation");
2211+
}
2212+
2213+
double startValue = _overlayGrid.Opacity;
2214+
double endValue = shouldShowOverlay ? DefaultOverlayOpacity : 0;
2215+
2216+
var overlayGridAnimation = new Animation(d =>
2217+
{
2218+
if (!double.IsNaN(d))
21692219
{
2170-
if (State is BottomSheetState.Collapsed || State is BottomSheetState.Hidden)
2171-
{
2172-
startValue = _overlayGrid.Opacity;
2173-
endValue = 0;
2174-
}
2175-
else
2176-
{
2177-
startValue = _overlayGrid.Opacity;
2178-
endValue = DefaultOverlayOpacity;
2179-
}
2220+
_overlayGrid.Opacity = d;
2221+
}
2222+
}, startValue, endValue);
21802223

2181-
var overlayGridAnimation = new Animation(d =>
2224+
_overlayGrid.Animate("overlayGridAnimation", overlayGridAnimation,
2225+
length: (uint)animationDuration,
2226+
easing: Easing.Linear,
2227+
finished: (v, c) =>
2228+
{
2229+
if (!shouldShowOverlay)
21822230
{
2183-
// Ensure the opacity is only updated with valid numeric values to avoid rendering issues.
2184-
if (!double.IsNaN(d))
2185-
{
2186-
_overlayGrid.Opacity = d;
2187-
}
2231+
RemoveOverlayFromView();
21882232
}
2189-
, startValue, endValue);
2190-
_overlayGrid.Animate("overlayGridAnimation", overlayGridAnimation,
2191-
length: (uint)animationDuration,
2192-
easing: Easing.Linear,
2193-
finished: (e, v) =>
2194-
{
2195-
if (State is BottomSheetState.Collapsed || State is BottomSheetState.Hidden)
2196-
{
2197-
_overlayGrid.IsVisible = false;
2198-
}
2199-
});
2200-
}
2201-
}
2233+
});
22022234
}
22032235

22042236
/// <summary>
@@ -2342,16 +2374,29 @@ AllowedState is BottomSheetAllowedState.HalfExpanded &&
23422374
/// <param name="touchY">The current Y coordinate of the touch point.</param>
23432375
void UpdateBottomSheetPosition(double newTranslationY, double touchY)
23442376
{
2345-
if (_bottomSheet is null || _overlayGrid is null)
2377+
if (_bottomSheet is null)
23462378
{
23472379
return;
23482380
}
23492381

23502382
_bottomSheet.TranslationY = newTranslationY;
23512383
_initialTouchY = touchY;
23522384
_bottomSheet.HeightRequest = Height - newTranslationY;
2353-
_overlayGrid.IsVisible = IsModal && (_bottomSheet.HeightRequest > CollapsedHeight);
2354-
_overlayGrid.Opacity = CalculateOverlayOpacity(_bottomSheet.HeightRequest);
2385+
// Manage overlay visibility during touch
2386+
bool shouldShowOverlay = IsModal && (_bottomSheet.HeightRequest > CollapsedHeight);
2387+
2388+
if (shouldShowOverlay)
2389+
{
2390+
AddOverlayToView();
2391+
if (_overlayGrid is not null)
2392+
{
2393+
_overlayGrid.Opacity = CalculateOverlayOpacity(_bottomSheet.HeightRequest);
2394+
}
2395+
}
2396+
else
2397+
{
2398+
RemoveOverlayFromView();
2399+
}
23552400
}
23562401

23572402
/// <summary>
@@ -2517,12 +2562,18 @@ static void OnIsModalPropertyChanged(BindableObject bindable, object oldValue, o
25172562
{
25182563
if (bindable is SfBottomSheet sheet)
25192564
{
2520-
if (sheet._overlayGrid is not null && (sheet.State is BottomSheetState.FullExpanded || sheet.State is BottomSheetState.HalfExpanded))
2521-
{
2522-
sheet._overlayGrid.IsVisible = sheet.IsModal;
2565+
bool isModal = (bool)newValue;
2566+
2567+
if (isModal && (sheet.State is BottomSheetState.FullExpanded or BottomSheetState.HalfExpanded))
2568+
{
2569+
sheet.AddOverlayToView();
25232570
sheet.AnimateOverlay(150);
2524-
}
2525-
}
2571+
}
2572+
else if (!isModal)
2573+
{
2574+
sheet.RemoveOverlayFromView();
2575+
}
2576+
}
25262577
}
25272578

25282579

maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Navigation/SfBottomSheetUnitTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void Constructor_InitializesDefaultsCorrectly()
3838
Assert.Equal(4d, _bottomSheet.GrabberHeight);
3939
Assert.Equal(32d, _bottomSheet.GrabberWidth);
4040
Assert.Equal(12d, _bottomSheet.GrabberCornerRadius);
41-
Assert.Equal(150d, _bottomSheet.AnimationDuration);
41+
Assert.Equal(150d,_bottomSheet.AnimationDuration);
4242
if (_bottomSheet.GrabberBackground is SolidColorBrush grabberBrush)
4343
{
4444
var grabberColor = grabberBrush.Color;
@@ -564,7 +564,7 @@ public void InitializeLayout()
564564
var bottomSheet = GetPrivateField(_bottomSheet, "_bottomSheet");
565565
var overlayGrid = GetPrivateField(_bottomSheet, "_overlayGrid");
566566
Assert.True(_bottomSheet.Children?.Contains(bottomSheet));
567-
Assert.True(_bottomSheet.Children?.Contains(overlayGrid));
567+
Assert.False(_bottomSheet.Children?.Contains(overlayGrid));
568568
}
569569

570570
[Fact]
@@ -592,7 +592,7 @@ public void InitializeOverlayGrid()
592592
Grid? overlayGrid = (Grid?)GetPrivateField(_bottomSheet, "_overlayGrid");
593593
Assert.Equal(overlayGrid?.BackgroundColor, Color.FromArgb("#80000000"));
594594
Assert.Equal(overlayGrid?.Opacity, 0.5);
595-
Assert.Equal(overlayGrid?.IsVisible, false);
595+
Assert.Equal(overlayGrid?.IsVisible, true);
596596
}
597597

598598
[Fact]
@@ -852,24 +852,24 @@ public void UpdateStateChanged(BottomSheetState oldState, BottomSheetState newSt
852852

853853
[Theory]
854854
[InlineData(true, true)]
855-
[InlineData(false, false)]
855+
[InlineData(false, true)]
856856
public void SetupBottomSheetForShow(bool input, bool expected)
857857
{
858858
_bottomSheet.IsModal = input;
859859
InvokePrivateMethod(_bottomSheet, "SetupBottomSheetForShow");
860860
SfGrid? overlay = (SfGrid?)GetPrivateField(_bottomSheet, "_overlayGrid");
861861
SfBorder? bottomsheet = (SfBorder?)GetPrivateField(_bottomSheet, "_bottomSheet");
862862
Assert.True(bottomsheet?.IsVisible);
863-
Assert.Equal(0, overlay?.Opacity);
863+
Assert.Equal(0.5, overlay?.Opacity);
864864
Assert.Equal(expected, overlay?.IsVisible);
865865
}
866866

867867
[Fact]
868868
public void GetCollapsedPosition()
869869
{
870870
InvokePrivateMethod(_bottomSheet, "GetCollapsedPosition");
871-
SfGrid? overlay = (SfGrid?)GetPrivateField(_bottomSheet, "_overlayGrid");
872-
Assert.False(overlay?.IsVisible);
871+
var overlay = GetPrivateField(_bottomSheet, "_overlayGrid");
872+
Assert.False(_bottomSheet.Children?.Contains(overlay));
873873
}
874874

875875
[Fact]

0 commit comments

Comments
 (0)