Skip to content

Commit 6d8d35d

Browse files
Merge pull request #83 from saiganesh-sakthivel/main
Fixed the segmentedcontrol keyboard navigation and accessibility issue in windows
2 parents 3d64db3 + 6f0a512 commit 6d8d35d

File tree

4 files changed

+85
-61
lines changed

4 files changed

+85
-61
lines changed

maui/src/SegmentedControl/Interface/ISegmentInfo.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,6 @@ internal interface ISegmentItemInfo : ISegmentInfo
130130
/// </summary>
131131
void ClearFocusedView();
132132

133-
#if WINDOWS
134-
/// <summary>
135-
/// Update the keyboard focused view for the segmentedControl.
136-
/// </summary>
137-
void SetFocusVisualState(bool state);
138-
#endif
139-
140133
/// <summary>
141134
/// Updates the scroll view position to focused index for the segment item.
142135
/// </summary>

maui/src/SegmentedControl/SfSegmentedControl.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ public SfSegmentedControl()
9292
MinimumHeightRequest = 40;
9393
SelectionIndicatorSettings.Parent = this;
9494
TextStyle.Parent = this;
95+
#if !WINDOWS
9596
this.AddKeyboardListener(this);
97+
#endif
9698
}
9799

98100
#endregion
@@ -1189,16 +1191,6 @@ void ISegmentItemInfo.ClearFocusedView()
11891191
_keyNavigationView?.ClearFocusedView();
11901192
}
11911193

1192-
#if WINDOWS
1193-
void ISegmentItemInfo.SetFocusVisualState(bool state)
1194-
{
1195-
if (this.Handler != null && this.Handler.PlatformView != null && this.Handler.PlatformView is Microsoft.UI.Xaml.UIElement nativeView)
1196-
{
1197-
nativeView.UseSystemFocusVisuals = state;
1198-
}
1199-
}
1200-
#endif
1201-
12021194
/// <summary>
12031195
/// Updates the scroll view position to focused index for the segment item.
12041196
/// </summary>

maui/src/SegmentedControl/Views/SegmentItemView.cs

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Syncfusion.Maui.Toolkit.SegmentedControl
99
/// <summary>
1010
/// Represents a view used to display an individual segment item within a segmented control.
1111
/// </summary>
12-
internal partial class SegmentItemView : SfContentView, ITouchListener, ITapGestureListener
12+
internal partial class SegmentItemView : SfContentView, ITouchListener, ITapGestureListener, IKeyboardListener
1313
{
1414
#region Fields
1515

@@ -70,10 +70,15 @@ internal SegmentItemView(ISegmentItemInfo itemInfo, SfSegmentItem item)
7070
InitializeEffectsView();
7171
this.AddTouchListener(this);
7272
this.AddGestureListener(this);
73+
#if WINDOWS
74+
this.AddKeyboardListener(this);
75+
#endif
7376
if (itemInfo?.SegmentTemplate != null)
7477
{
7578
CreateSegmentItemTemplateView();
7679
}
80+
81+
UpdateSemantics();
7782
}
7883

7984
#endregion
@@ -107,6 +112,7 @@ internal void UpdateSelection()
107112
_isSelected = true;
108113
_selectionView?.UpdateVisualState(true);
109114
InvalidateDrawable();
115+
UpdateSemantics();
110116
}
111117

112118
/// <summary>
@@ -123,6 +129,7 @@ internal void ClearSelection()
123129
_isSelected = false;
124130
_selectionView.UpdateVisualState(_isSelected, false);
125131
InvalidateDrawable();
132+
UpdateSemantics();
126133
}
127134

128135
/// <summary>
@@ -420,6 +427,9 @@ void InitializeImageView()
420427
#endif
421428
};
422429

430+
#if WINDOWS
431+
AutomationProperties.SetIsInAccessibleTree(_imageView, false);
432+
#endif
423433
Children.Add(_imageView);
424434
}
425435

@@ -435,6 +445,9 @@ void InitializeSelectionView()
435445
}
436446

437447
_selectionView = new SelectionView(_segmentItem, itemInfo);
448+
#if WINDOWS
449+
AutomationProperties.SetIsInAccessibleTree(_selectionView, false);
450+
#endif
438451
Children.Add(_selectionView);
439452
}
440453

@@ -453,6 +466,9 @@ void InitializeEffectsView()
453466
_effectsView.ShouldIgnoreTouches = true;
454467
_effectsView.AnimationCompleted += OnEffectsViewAnimationCompleted;
455468
_effectsView.ClipToBounds = true;
469+
#if WINDOWS
470+
AutomationProperties.SetIsInAccessibleTree(_effectsView, false);
471+
#endif
456472
Children.Add(_effectsView);
457473
}
458474

@@ -597,6 +613,28 @@ void RemoveEffects()
597613
_effectsView.Reset();
598614
}
599615

616+
/// <summary>
617+
/// Method to update the semantic properties.
618+
/// </summary>
619+
void UpdateSemantics()
620+
{
621+
if (_segmentItem != null)
622+
{
623+
if (!string.IsNullOrEmpty(SemanticProperties.GetDescription(_segmentItem)))
624+
{
625+
SemanticProperties.SetDescription(this, SemanticProperties.GetDescription(_segmentItem));
626+
}
627+
else if (!_segmentItem.IsEnabled || (itemInfo != null && !itemInfo.IsEnabled))
628+
{
629+
SemanticProperties.SetDescription(this, _segmentItem.Text + SfSegmentedResources.GetLocalizedString("Disabled"));
630+
}
631+
else
632+
{
633+
SemanticProperties.SetDescription(this, _isSelected ? _segmentItem.Text + SfSegmentedResources.GetLocalizedString("Selected") : _segmentItem.Text);
634+
}
635+
}
636+
}
637+
600638
/// <summary>
601639
/// Method to remove the selection view handlers.
602640
/// </summary>
@@ -746,7 +784,11 @@ protected override void OnDraw(ICanvas canvas, RectF dirtyRect)
746784
semanticsNode.OnClick = OnSemanticsNodeClick;
747785
}
748786
string text = _segmentItem.Text;
749-
if (!_segmentItem.IsEnabled || (itemInfo != null && !itemInfo.IsEnabled))
787+
if (!string.IsNullOrEmpty(SemanticProperties.GetDescription(_segmentItem)))
788+
{
789+
semanticsNode.Text = SemanticProperties.GetDescription(_segmentItem);
790+
}
791+
else if (!_segmentItem.IsEnabled || (itemInfo != null && !itemInfo.IsEnabled))
750792
{
751793
semanticsNode.Text = text + SfSegmentedResources.GetLocalizedString("Disabled");
752794
}
@@ -758,6 +800,21 @@ protected override void OnDraw(ICanvas canvas, RectF dirtyRect)
758800
return [semanticsNode];
759801
}
760802

803+
#if WINDOWS
804+
/// <summary>
805+
/// Raises when <see cref="SegmentItemView"/>'s handler gets changed.
806+
/// <exclude/>
807+
/// </summary>
808+
protected override void OnHandlerChanged()
809+
{
810+
base.OnHandlerChanged();
811+
if (this.Handler != null && this.Handler.PlatformView != null && this.Handler.PlatformView is Microsoft.UI.Xaml.UIElement nativeView)
812+
{
813+
nativeView.IsTabStop = true;
814+
}
815+
}
816+
#endif
817+
761818
/// <summary>
762819
/// Measures the size of the view's content based on the specified constraints.
763820
/// </summary>
@@ -875,6 +932,30 @@ void ITapGestureListener.OnTap(Syncfusion.Maui.Toolkit.Internals.TapEventArgs e)
875932
#endif
876933
}
877934

935+
/// <summary>
936+
/// Gets a value indicating whether the view can become the first responder to listen the keyboard actions.
937+
/// </summary>
938+
/// <remarks>This property will be considered only in iOS Platform.</remarks>
939+
bool IKeyboardListener.CanBecomeFirstResponder
940+
{
941+
get { return true; }
942+
}
943+
944+
/// <inheritdoc/>
945+
void IKeyboardListener.OnKeyDown(KeyEventArgs e)
946+
{
947+
if (e.Key == KeyboardKey.Enter)
948+
{
949+
UpdateSelectedIndex();
950+
}
951+
}
952+
953+
/// <inheritdoc/>
954+
void IKeyboardListener.OnKeyUp(KeyEventArgs args)
955+
{
956+
957+
}
958+
878959
#endregion
879960
}
880961
}

maui/src/SegmentedControl/Views/SegmentLayout.cs

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ namespace Syncfusion.Maui.Toolkit.SegmentedControl
66
/// <summary>
77
/// Represents a layout for arranging and displaying a collection of segment items.
88
/// </summary>
9-
#if WINDOWS
10-
internal partial class SegmentLayout : SfView, IKeyboardListener
11-
#else
129
internal class SegmentLayout : SfView
13-
#endif
1410
{
1511
#region Fields
1612

@@ -50,9 +46,6 @@ internal SegmentLayout(ISegmentItemInfo itemInfo)
5046
_itemInfo = itemInfo;
5147
DrawingOrder = DrawingOrder.AboveContent;
5248
InitializeSegmentItemsView();
53-
#if WINDOWS
54-
this.AddKeyboardListener(this);
55-
#endif
5649
}
5750

5851
#endregion
@@ -196,21 +189,11 @@ internal void ProcessOnKeyDown(KeyEventArgs e)
196189
_focusedIndex = -1;
197190
}
198191

199-
#if WINDOWS
200-
if (e.Key == KeyboardKey.Left || e.Key == KeyboardKey.Right)
201-
{
202-
_itemInfo?.SetFocusVisualState(false);
203-
}
204-
#endif
205-
206192
if (e.Key == KeyboardKey.Tab || (e.Key == KeyboardKey.Tab && e.IsShiftKeyPressed) || e.Key == KeyboardKey.Down || e.Key == KeyboardKey.Up)
207193
{
208194
e.Handled = false;
209195
_focusedIndex = -1;
210196
_itemInfo?.ClearFocusedView();
211-
#if WINDOWS
212-
_itemInfo?.SetFocusVisualState(true);
213-
#endif
214197
return;
215198
}
216199

@@ -849,30 +832,5 @@ protected override Size ArrangeContent(Rect bounds)
849832
}
850833

851834
#endregion
852-
853-
#region Interface implementation
854-
#if WINDOWS
855-
/// <summary>
856-
/// Gets a value indicating whether the view can become the first responder to listen the keyboard actions.
857-
/// </summary>
858-
/// <remarks>This property will be considered only in iOS Platform.</remarks>
859-
bool IKeyboardListener.CanBecomeFirstResponder
860-
{
861-
get { return true; }
862-
}
863-
864-
/// <inheritdoc/>
865-
void IKeyboardListener.OnKeyDown(KeyEventArgs e)
866-
{
867-
ProcessOnKeyDown(e);
868-
}
869-
870-
/// <inheritdoc/>
871-
void IKeyboardListener.OnKeyUp(KeyEventArgs e)
872-
{
873-
874-
}
875-
#endif
876-
#endregion
877835
}
878836
}

0 commit comments

Comments
 (0)