Skip to content

Commit 4d2e43e

Browse files
Added bottom sheet control changes
1 parent 1d0f3bd commit 4d2e43e

File tree

9 files changed

+2812
-1
lines changed

9 files changed

+2812
-1
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using Syncfusion.Maui.Toolkit.Helper;
2+
using Syncfusion.Maui.Toolkit.Internals;
3+
4+
namespace Syncfusion.Maui.Toolkit.BottomSheet
5+
{
6+
/// <summary>
7+
/// Represents the <see cref="BottomSheetBorder"/> that defines the layout of bottom sheet.
8+
/// </summary>
9+
internal class BottomSheetBorder : SfBorder, ITouchListener
10+
{
11+
#region Fields
12+
13+
// To store the weak reference of bottom sheet instance.
14+
readonly WeakReference<SfBottomSheet>? _bottomSheetRef;
15+
16+
#endregion
17+
18+
#region Constructor
19+
20+
/// <summary>
21+
/// Initializes a new instance of the <see cref="BottomSheetBorder"/> class.
22+
/// </summary>
23+
/// <param name="bottomSheet">The SfBottomSheet instance.</param>
24+
/// <exception cref="ArgumentNullException">Thrown if bottomSheet is null.</exception>
25+
public BottomSheetBorder(SfBottomSheet bottomSheet)
26+
{
27+
if (bottomSheet is not null)
28+
{
29+
_bottomSheetRef = new WeakReference<SfBottomSheet>(bottomSheet);
30+
this.AddTouchListener(this);
31+
}
32+
}
33+
34+
#endregion
35+
36+
#region Interface Implementation
37+
38+
/// <summary>
39+
/// Method to invoke swiping in bottom sheet.
40+
/// </summary>
41+
/// <param name="e">e.</param>
42+
public void OnTouch(Toolkit.Internals.PointerEventArgs e)
43+
{
44+
#if IOS || MACCATALYST || ANDROID
45+
if (e is not null && _bottomSheetRef is not null)
46+
{
47+
if (_bottomSheetRef.TryGetTarget(out var bottomSheet))
48+
{
49+
bottomSheet.OnHandleTouch(e.Action, e.TouchPoint);
50+
}
51+
}
52+
#endif
53+
}
54+
#endregion
55+
}
56+
}

maui/src/BottomSheet/Enum.cs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
namespace Syncfusion.Maui.Toolkit.BottomSheet
2+
{
3+
/// <summary>
4+
/// Specifies the current display state of the SfBottomSheet control.
5+
/// </summary>
6+
/// <remarks>
7+
/// This enum is used to represent the various possible states of the bottom sheet,
8+
/// allowing for precise control and state management of the UI component.
9+
/// </remarks>
10+
public enum BottomSheetState
11+
{
12+
/// <summary>
13+
/// Indicates that the bottom sheet is fully expanded to cover the entire screen.
14+
/// </summary>
15+
FullExpanded,
16+
17+
/// <summary>
18+
/// Represents the state where the bottom sheet is expanded to cover approximately half of the screen.
19+
/// </summary>
20+
HalfExpanded,
21+
22+
/// <summary>
23+
/// Denotes that the bottom sheet is in its minimized or collapsed state, typically showing only a small portion or header.
24+
/// </summary>
25+
Collapsed,
26+
27+
/// <summary>
28+
/// Signifies that the bottom sheet is completely hidden from view.
29+
/// </summary>
30+
Hidden
31+
}
32+
33+
/// <summary>
34+
/// Defines the allowable states for the SfBottomSheet control.
35+
/// </summary>
36+
/// <remarks>
37+
/// This enum is used to configure the permitted states of the bottom sheet,
38+
/// enabling developers to restrict or allow specific display modes.
39+
/// </remarks>
40+
public enum BottomSheetAllowedState
41+
{
42+
/// <summary>
43+
/// Configures the bottom sheet to only allow full screen expansion.
44+
/// When set, the bottom sheet can only be fully expanded or hidden.
45+
/// </summary>
46+
FullExpanded,
47+
48+
/// <summary>
49+
/// Restricts the bottom sheet to only permit half screen expansion.
50+
/// When set, the bottom sheet can only be half expanded or hidden.
51+
/// </summary>
52+
HalfExpanded,
53+
54+
/// <summary>
55+
/// Allows the bottom sheet to be displayed in both full screen and half screen modes.
56+
/// This option provides the most flexibility, permitting all possible states.
57+
/// </summary>
58+
All
59+
}
60+
61+
/// <summary>
62+
/// Defines the content width mode for the SfBottomSheet control.
63+
/// </summary>
64+
public enum BottomSheetContentWidthMode
65+
{
66+
/// <summary>
67+
/// The BottomSheet will span the full width of the parent container.
68+
/// </summary>
69+
Full,
70+
71+
/// <summary>
72+
/// The BottomSheet will use a custom width value, centered if not full width.
73+
/// </summary>
74+
Custom
75+
}
76+
}
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
using Microsoft.UI.Xaml.Input;
2+
using Microsoft.UI.Xaml;
3+
using Syncfusion.Maui.Toolkit.Internals;
4+
5+
namespace Syncfusion.Maui.Toolkit.BottomSheet
6+
{
7+
public partial class SfBottomSheet
8+
{
9+
#region Fields
10+
11+
/// <summary>
12+
/// The native platform view of the bottom sheet, used for handling touch and manipulation events.
13+
/// </summary>
14+
FrameworkElement? _bottomSheetNativeView;
15+
16+
/// <summary>
17+
/// A flag indicating whether a manipulation gesture (e.g., drag) has started on the bottom sheet.
18+
/// </summary>
19+
bool _isManipulationStarted;
20+
21+
/// <summary>
22+
/// A flag that tracks whether the touch event has been handled, specifically for touch devices.
23+
/// </summary>
24+
bool _isTouchHandled;
25+
26+
#endregion
27+
28+
#region Override Methods
29+
30+
/// <summary>
31+
/// Raises on handler changing.
32+
/// </summary>
33+
/// <param name="args">Handler changing event arguments.</param>
34+
protected override void OnHandlerChanging(HandlerChangingEventArgs args)
35+
{
36+
base.OnHandlerChanging(args);
37+
}
38+
39+
#endregion
40+
41+
#region Private Methods
42+
43+
/// <summary>
44+
/// Configures touch events based on the availability of the platform-specific view.
45+
/// </summary>
46+
void ConfigureTouch()
47+
{
48+
if (Handler is not null && Handler.PlatformView is not null)
49+
{
50+
WireEvents();
51+
}
52+
else
53+
{
54+
UnWireEvents();
55+
}
56+
}
57+
58+
/// <summary>
59+
/// Attaches necessary touch and manipulation event handlers to the platform-specific view.
60+
/// </summary>
61+
void WireEvents()
62+
{
63+
if (Handler is not null && Handler.PlatformView is not null && Handler.PlatformView is FrameworkElement)
64+
{
65+
_bottomSheetNativeView = Handler.PlatformView as FrameworkElement;
66+
if (_bottomSheetNativeView is not null)
67+
{
68+
_bottomSheetNativeView.ManipulationMode = ManipulationModes.All;
69+
_bottomSheetNativeView.ManipulationStarted += OnManipulationStarted;
70+
_bottomSheetNativeView.PointerPressed += OnPointerPressed;
71+
_bottomSheetNativeView.ManipulationDelta += OnManipulationDelta;
72+
_bottomSheetNativeView.ManipulationCompleted += OnManipulationCompleted;
73+
_bottomSheetNativeView.PointerReleased += OnPointerReleased;
74+
_bottomSheetNativeView.PointerMoved += OnPointerMoved;
75+
}
76+
}
77+
}
78+
79+
/// <summary>
80+
/// Detaches previously attached touch and manipulation event handlers from the platform-specific view.
81+
/// </summary>
82+
void UnWireEvents()
83+
{
84+
if (Handler is not null && Handler.PlatformView is not null)
85+
{
86+
_bottomSheetNativeView = Handler.PlatformView as FrameworkElement;
87+
if (_bottomSheetNativeView is not null)
88+
{
89+
_bottomSheetNativeView.ManipulationMode = ManipulationModes.All;
90+
_bottomSheetNativeView.ManipulationStarted -= OnManipulationStarted;
91+
_bottomSheetNativeView.PointerPressed -= OnPointerPressed;
92+
_bottomSheetNativeView.ManipulationDelta -= OnManipulationDelta;
93+
_bottomSheetNativeView.ManipulationCompleted -= OnManipulationCompleted;
94+
_bottomSheetNativeView.PointerReleased -= OnPointerReleased;
95+
_bottomSheetNativeView.PointerMoved -= OnPointerMoved;
96+
}
97+
}
98+
}
99+
100+
/// <summary>
101+
/// Handles the start of a manipulation gesture on the platform-specific view.
102+
/// </summary>
103+
/// <param name="sender">The source of the event, typically the platform view.</param>
104+
/// <param name="e">The manipulation started event arguments containing position details.</param>
105+
void OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
106+
{
107+
if (!_isPointerPressed && _bottomSheet is not null)
108+
{
109+
if (e.Position.Y < _bottomSheet.TranslationY)
110+
{
111+
return;
112+
}
113+
114+
// Handle the start of the manipulation
115+
OnHandleTouch(PointerActions.Pressed, new Point(e.Position.X, e.Position.Y));
116+
_isManipulationStarted = true;
117+
}
118+
}
119+
120+
/// <summary>
121+
/// Handles the pointer press action on the platform-specific view.
122+
/// </summary>
123+
/// <param name="sender">The source of the event, typically the platform view.</param>
124+
/// <param name="e">Pointer routed event arguments containing pointer details.</param>
125+
void OnPointerPressed(object sender, PointerRoutedEventArgs e)
126+
{
127+
if (_bottomSheetNativeView is not null && _bottomSheet is not null)
128+
{
129+
// Get the pointer position relative to the view
130+
var point = e.GetCurrentPoint(_bottomSheetNativeView).Position;
131+
if (point.Y < _bottomSheet.TranslationY)
132+
{
133+
return;
134+
}
135+
136+
// Handle the pointer press action
137+
OnHandleTouch(PointerActions.Pressed, new Point(point.X, point.Y));
138+
}
139+
140+
if (e.Pointer.PointerDeviceType == Microsoft.UI.Input.PointerDeviceType.Touch)
141+
{
142+
_isTouchHandled = true;
143+
}
144+
else
145+
{
146+
_isTouchHandled = false;
147+
}
148+
}
149+
150+
/// <summary>
151+
/// Handles the pointer move action on the platform-specific view.
152+
/// </summary>
153+
/// <param name="sender">The source of the event, typically the platform view.</param>
154+
/// <param name="e">Pointer routed event arguments containing pointer details.</param>
155+
void OnPointerMoved(object sender, PointerRoutedEventArgs e)
156+
{
157+
if (e.Pointer.PointerDeviceType == Microsoft.UI.Input.PointerDeviceType.Mouse && _isTouchHandled)
158+
{
159+
return;
160+
}
161+
162+
if (_isPointerPressed && _bottomSheetNativeView is not null)
163+
{
164+
// Get the pointer position relative to the view
165+
var point = e.GetCurrentPoint(_bottomSheetNativeView).Position;
166+
// Handle the pointer move action
167+
OnHandleTouch(PointerActions.Moved, new Point(point.X, point.Y));
168+
}
169+
}
170+
171+
/// <summary>
172+
/// Handles the pointer release action on the platform-specific view.
173+
/// </summary>
174+
/// <param name="sender">The source of the event, typically the platform view.</param>
175+
/// <param name="e">Pointer routed event arguments containing pointer details.</param>
176+
void OnPointerReleased(object sender, PointerRoutedEventArgs e)
177+
{
178+
if (_bottomSheetNativeView is not null)
179+
{
180+
var point = e.GetCurrentPoint(_bottomSheetNativeView).Position;
181+
OnHandleTouch(PointerActions.Released, new Point(point.X, point.Y));
182+
}
183+
184+
_isManipulationStarted = false;
185+
_isTouchHandled = false;
186+
}
187+
188+
/// <summary>
189+
/// Handles the completion of a manipulation gesture on the platform-specific view.
190+
/// </summary>
191+
/// <param name="sender">The source of the event, typically the platform view.</param>
192+
/// <param name="e">Manipulation completed event arguments containing details about the gesture.</param>
193+
void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
194+
{
195+
if (_isPointerPressed && _isManipulationStarted)
196+
{
197+
// Handle the release action at the end of manipulation.
198+
OnHandleTouch(PointerActions.Released, new Point(e.Position.X, e.Position.Y));
199+
// Reset the manipulation state
200+
_isManipulationStarted = false;
201+
}
202+
}
203+
204+
/// <summary>
205+
/// Handles the ongoing manipulation action (such as drag) as the user moves their pointer.
206+
/// </summary>
207+
/// <param name="sender">The source of the event, typically the platform view.</param>
208+
/// <param name="e">Manipulation delta event arguments containing details about the ongoing manipulation.</param>
209+
void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
210+
{
211+
if (_isPointerPressed && _isManipulationStarted)
212+
{
213+
// Handle the intermediate manipulation action
214+
OnHandleTouch(PointerActions.Moved, new Point(e.Position.X, e.Position.Y));
215+
216+
// Check for boundary conditions
217+
if (e.Position.Y < 0 || e.Position.Y > Height)
218+
{
219+
// Handle the release action if outside of content width
220+
OnHandleTouch(PointerActions.Released, new Point(e.Position.X, e.Position.Y));
221+
}
222+
}
223+
}
224+
225+
#endregion
226+
}
227+
}

0 commit comments

Comments
 (0)