Set accessibility order
On Android, you can set the accessibility order in XML, or modify the accessibility order in code. You can use the android:accessibilityTraversalAfter and and android:accessibilityTraversalBefore properties in XML. Or you can use the setAccessibilityTraversalBefore) and setAccessibilityTraversalAfter) methods in code.
xml
<TextView
android:id="@+id/header" />
<RecyclerView
android:id="@+id/list"
android:accessibilityTraversalAfter="@id/description" />
<TextView
android:id="@+id/description"
android:accessibilityTraversalBefore="@id/header" /> kotlin
header.setAccessibilityTraversalBefore(R.id.description)
list.setAccessibilityTraversalAfter(R.id.description) In Jetpack Compose, you can use the traversalIndex.traversalIndex()) to alter the focus order of the screen. The traversalIndex will give assistive technologies an explicit order of traversing.
When a section of a screen is read out in an incorrect order, start by adding isTraversalGroup.isTraversalGroup()) to the parent Column, Row or Box. This will let assistive technologies know that this section is grouped and should be traversed, before moving on to a next section. Then add traversalIndex to elements in this group to fix any issues with the focus order.
It is possible to use isTraversalGroup and traversalIndex on the same element.
kotlin
Box(modifier = Modifier.semantics {
isTraversalGroup = true
traversalIndex = -1f
}) {
// Box content...
} On iOS, you can use the accessibilityElements property to set the order for assistive technologies. Be careful using the accessibilityElements property, because any elements left out of the array cannot be reached with assistive technologies.
swift
view.accessibilityElements = [header, description, list] In SwiftUI, assistive technology like VoiceOver typically reads elements in a top-left to bottom-right order. However, you can customize this reading order using the accessibilitySortPriority) view modifier. A higher priority value means the element is read earlier. Use .accessibilityElement(children: .contain) to group and manage the accessibility elements within stacks (HStack, VStack, or ZStack) to improve navigation when using assitive technologies.
swift
VStack {
Text("First Element")
.accessibilitySortPriority(2) // Reads second
Text("Second Element")
.accessibilitySortPriority(3) // Reads first
Text("Third Element")
.accessibilitySortPriority(1) // Reads third
}
.accessibilityElement(children: .contain) // Groups the stack's children For sorting the focus order in Flutter apps, the sortKey parameter of Semantics is used.
This parameter uses a SemanticsSortKey to sort the elements. The most common way to sort elements is the OrdinalSortKey, but you can also write your own implementation based on the SemanticsSortKey class.
The OrdinalSortKey needs an order as double and optionally a name as String. The elements are then sorted by name, with empty names handled first, and subsequently by order.
It is also possible to leave out the sortKey. In this case, Flutter will generate OrdinalSortKey's based on a platform specific algorithm. This order is often the order you want, but make sure to verify the sequence by using an assistive technology such as the screen reader.
dart
Widget focusOrderWidget(context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Semantics(
sortKey: OrdinalSortKey(2.0),
child: Text("Second focus")
),
Semantics(
sortKey: OrdinalSortKey(1.0),
child: Text("First focus")
)
],
)
)
);
} React Native does not have support for changing the focus order. You can use the accessible prop to indicate that a view should be focusable. The child elements get grouped together.
More information about the lack of support for changing accessibility order can be found inside Discussion 389 of the React Native Community.
jsx
Not available, contribute! In MAUI, you can use a SemanticOrderView to control the order of VisualElements for screen readers. This can be particularly useful when building user interfaces in orders differing from the order in which users and screen readers will navigate them.
For more information, check out the SemanticOrderView documentation.
xml
<ContentPage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="CommunityToolkit.Maui.Sample.Pages.Views.SemanticOrderViewPage"
Title="Semantic Order View">
<ContentPage.Content>
<toolkit:SemanticOrderView x:Name="SemanticOrderView">
<Grid RowDefinitions="*,2*,*">
<Label Grid.Row="0" x:Name="DescriptionLabel" Text="Label for description, first label in xaml file" />
<Label Grid.Row="1" x:Name="TitleLabel" Text="Title, second label in xaml file" FontSize="30" />
<Label Grid.Row="2" Text="This label is excluded in the accessibility tree on iOS" />
</Grid>
</toolkit:SemanticOrderView>
</ContentPage.Content>
</ContentPage> csharp
using System.Collections.Generic;
namespace CommunityToolkit.Maui.Sample.Pages.Views;
public partial class SemanticOrderViewPage : ContentPage
{
public SemanticOrderViewPage()
{
InitializeComponent();
this.SemanticOrderView.ViewOrder = new List<View> { TitleLabel, DescriptionLabel };
}
} Xamarin Forms supports changing the accessibility order through the TabIndex property. The default value is 0. The lower the value, the higher the priority. For example, to reach the save button before reaching the cancel button, the cancel button's TabIndex needs to be higher than the save button.
xml
<Label Text="Appt" />
<Button x:Name="cancelButton" TabIndex="20" />
<Button x:Name="saveButton" TabIndex="10"/>