Build more accessible apps in .NET MAUI with semantic properties

by: | Jan 26, 2023

Microsoft’s .NET MAUI is a popular solution for developers to create cross-platform applications. Introduced in 2022 as a successor to Xamarin, it offers a modern approach to developing apps with a single code base. One of the improvements in .NET MAUI is semantic properties, a better way to build more accessible apps.

Resources for Xamarin developers:

Why build accessible apps?

According to the World Health Organization (WHO), more than 1 billion people experience some form of disability, which makes accessible app development so important. More accessible software products benefit everyone — not just people with disabilities. Many people prefer to use voice search and voice assistants, technologies that visually impaired users depend upon to navigate the global web. We cover this more in our Accessibilty-First philosophy, which is a core value at ArcTouch.

In this post I’ll explain how our Xamarin and .NET MAUI developers use semantic properties to build more accessible apps. I’ll also share useful tips to take full advantage of semantic properties.

banner ad to promote the ArcTouch App Accessibility Checklist

How to build accessible apps using .NET MAUI semantic properties

It’s all about screen readers

Screen readers are one of the most used technologies for helping people with disabilities navigate the digital world. As an accessible app developer, you should be aware of how they work.

Here’s how to enable a screen reader:

  • On Android: Go to Settings > Accessibility > TalkBack. Turn TalkBack on.
  • On iOS: Go to Settings > Accessibility > VoiceOver. Turn VoiceOver on.
  • On macOS: Go to System Preferences > Accessibility > VoiceOver. Turn VoiceOver on.
  • On Windows: Go to Settings > Ease of Access > Narrator. Turn Narrator on.

Perform the following exercises to familiarize yourself with screen readers:

  • On a desktop website, try to navigate using only the keyboard. You can also check the magnification and color contrast features.
  • Decrease the screen brightness to zero level and then try to navigate by swiping left to right with one finger in a mobile app.
  • See how the screen reader tutorials can help improve your navigation experience.
  • Pay close attention to how the screen reader experience differs from what you’re familiar with.

Semantic properties make screen readers perform better

Most screen readers automatically read any text associated with accessibility controls, but semantic properties improve this experience. Semantic properties help developers provide screen readers with useful data to read aloud to users. There are three properties: Description, Hint, and Heading Level. They can be also applied to the XAML file or in the C# code-behind (xaml.cs file).

Xamarin.Forms Automation Properties still works in .NET MAUI, but as you migrate your app from Xamarin to MAUI you should plan to switch to semantic properties.

SemanticProperties.Description is a short description that is read aloud by the screen reader. For example, if we don’t assign a value for Description, then the screen reader won’t be able to read anything out loud. Also, avoid setting this Description property on a label control, because this will stop the label’s text property from being automatically spoken by the screen reader. Instead, the Description content will be read:

<Image Source="dotnet_bot.png"
       SemanticProperties.Description="Cute dot net bot waving hi to you!" />

<Label Text="Hello world!"
       SemanticProperties.Description="The screen reader will read this content instead of the Hello World." />

Description can also be defined on another element through binding:

<Label x:Name="label"
       Text="Enter your name: " />
<Entry SemanticProperties.Description="{Binding Source={x:Reference label} Path=Text}" />

SemanticProperties.Hint is similar to Description — it also tells the screen reader what to read aloud, but is used to provide additional context about the purpose of the control to assist the user during navigation. That property conflicts with the Entry.Placeholder property on Android, because both map to the same platform property. With that said, make sure the text for both is the same:

<Button Text="Navigate"
        SemanticProperties.Hint="Click me to navigate to the next page" />

SemanticProperties.HeadingLevel enables an element to be marked as a heading to organize the UI and make it easier to navigate. Screen reader users can skip content and quickly jump between headings. It also has a level from 1 to 9:

<Label Text="Get started with .NET MAUI"
       SemanticProperties.HeadingLevel="Level1" />
<Label Text="Paragraphs of text go here." />
<Label Text="Installation"
       SemanticProperties.HeadingLevel="Level2" />
<Label Text="Paragraphs of text go here." />
<Label Text="Build your first app"
       SemanticProperties.HeadingLevel="Level3" />
<Label Text="Paragraphs of text go here." />
<Label Text="Publish your app"
       SemanticProperties.HeadingLevel="Level4" />
<Label Text="Paragraphs of text go here." />

Now that you understand the basics of how semantic properties work, here are some tips from our .NET MAUI experts to make screen readers even more effective.

Tip 1: Semantic extensions give screen readers focus

The SetSemanticFocus extension method forces the screen reader to focus on a specified element. For example, a button that when clicked sets the screen reader’s focus to another label to be read aloud:

<Button Text="Click me"
        SemanticProperties.Hint="Click to set semantic focus to the label below" />

<Label x:Name="semanticFocusLbl"
       Text="Label with semantic focus!" />

Here’s what the code-behind (xaml.cs file) is:

private void OnSemanticFocusClicked(object sender, EventArgs e) => semanticFocusLbl.SetSemanticFocus();

Tip 2: Make an announcement with Semantic Screen Reader

The ISemanticScreenReader interface enables a screen reader to announce text to the user. It doesn’t need to be tied to a specific control like the semantic properties. For example, this Announce method counts the number of times the user has clicked a button:

<Button x:Name="counterBtn"
        Text="Click me"
        SemanticProperties.Hint="Counts the number of times you click" />

Then on the xaml.cs file, we use the OnCounterClicked method:

private void OnCounterClicked(object sender, EventArgs e)
  counterBtn.Text = $"Clicked {count} " + (count > 1 ? "times" : "time");

Tip 3: Add accessibility traits for TapGestureRecognizer

Sometimes we develop custom controls with interactive actions, but the element isn’t always a simple button. That’s where TapGestureRecognizer comes in handy. If you need to attach a tap gesture recognizer to an element, .NET MAUI can inform screen readers that the element is clickable.

Let’s take the previous button count example and apply it to a given label we want to perform as a button for the screen reader:

<Label x:Name="counterLbl"
       Text="Click me"
       SemanticProperties.Hint="Counts the number of times you click"
       TextColor="White" />

On the code-behind (xaml.cs file), we can define a new TapGestureRecognizer:

var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) =>
  counterLbl.Text = $"Clicked {count} " + (count > 1 ? "times" : "time");

Tip 4: Organize UI content the way you want it read

The TabIndex and IsTabStop properties in Xamarin.Forms helped developers define the order in which UI elements would be read by a screen reader. Unfortunately, they were confusing and often misused, so these properties were removed from .NET MAUI. Instead, Microsoft recommends organizing your UI content on the device screen the same way you would want it to be read aloud by the screen reader — rather than trying to do it programmatically.

Tip 5: Add accessibility to .NET MAUI graphics

Maui.Graphics helps developers draw graphical objects in their apps. It supports drawing and painting shapes and images, and manipulating objects, including rotating, resizing, or reshaping. And by using semantic properties you can make a GraphicsView accessible:

<GraphicsView Drawable="{StaticResource GraphicsDrawable}"
              SemanticProperties.Description="Drawing of a big smile!" />

We can Draw our control in the GraphicsDrawable class:

public class GraphicsDrawable : IDrawable
  public void Draw(ICanvas canvas, RectF dirtyRect)
    // Left eye
    canvas.FillColor = Colors.CadetBlue;
    canvas.FillCircle(20, 20, 10);

    // Right eye
    canvas.FillColor = Colors.CadetBlue;
    canvas.FillCircle(80, 20, 10);

    // Smile
    canvas.StrokeColor = Colors.Teal;
    canvas.StrokeSize = 4;
    canvas.DrawArc(5, 1, 90, 90, 0, 180, true, false);

Tip 6: Test your .NET MAUI app’s accessibility

In addition to trying out your app’s accessibility using one of the screen readers mentioned at the start of this post, there are several helpful tools for testing the overall accessibility features of a .NET MAUI app. The Accessibility Inspector for iOS and macOS apps gets data from accessible elements in your app screen to display properties, values, and action methods, ensuring the objects contain the proper information. The Accessibility Scanner for Android scans the app screen and gives suggestions to improve the overall accessibility, including content labels, tappable items, and touch target size. Another good tool is the Colour Contrast Analyser, which checks if the application has enough contrast between foreground and background colors. You should use these tools in combination with a manual testing process.

Want to build an accessible .NET MAUI app?

If you’d like to discuss how to make your Xamarin apps or .NET MAUI apps more accessible and inclusive to a wider audience, contact us for a free consultation with our experts.