Accessibility in Xamarin.Forms
- PDF for offline use
- Related Links:
Let us know how you feel about this
Translation Quality
0/250
last updated: 2016-05
Making a Xamarin.Forms app accessible means thinking about the layout and design of many user interface elements. For some guidelines on what to consider, refer to the to the accessibility checklist for some guidelines on what to consider. Many accessibility concerns such as large fonts, and good color/contrast settings can already be addressed by Xamarin.Forms APIs.
The Android accessibility and iOS accessibility guides contain details of the native APIs exposed by Xamarin, and the UWP accessibility guide on MSDN explains the native approach on that platform. These APIs are used to fully implement accessible apps on each platform.
Xamarin.Forms does not currently have built-in support for the accessibility APIs available on each of the underlying platforms. This page provides an overview of how to support platform-specific accessibility APIs with custom code.
Describing UI Elements
Other than font, size, and color considerations, supporting screen-reader and navigation-assistance tools is the one of the most important parts of building accessible apps.
The sample code listed below includes a
Xamarin.Forms Effect
that can be used to expose the native accessibility APIs to better
support screen-reading and navigation accessibility tools.
Review the native Android and iOS accessibility features to understand the platform-specific APIs being used, and how the sample code could be extended.
Other Accessibility Features
Other accessibility APIs (such as PostNotification on iOS)
may be better suited to a DependencyService
or Custom Renderer implementation.
These are not covered in this guide.
Testing Accessibility
Xamarin.Forms apps typically target multiple platforms, which means testing the accessibility features differently according to the platform. Follow these links to learn how to test for each platform:
Sample AccessibilityEffect Code
Until a future release of Xamarin.Forms exposes accessibility APIs directly, the Xamarin.Forms effect code below can be used (and expanded upon) to build accessible applications using the current version of Xamarin.Forms.
About the Sample Code
Creating a Xamarin.Forms effect requires code in the common project (to define the API) and implementations in each platform-specific project:
- AccessibilityEffect – this class defines the API for the effect and belongs in the PCL or Shared Project.
- How to use the effect in XAML and C# – these examples show how to use the effect on Xamarin.Forms controls.
- iOS Implementation – iOS platform-specific code that applies the settings to native controls.
- Android Implementation – Android platform-specific code that applies the settings to native controls.
The API shown in the example below can be expanded to provide support for additional accessibility features.
Common Code (PCL or Shared)
This code belongs in the shared library containing the Xamarin.Forms application and user interface.
AccessibilityEffect
The AccessibilityEffect defines the API for adding accessible
elements to Xamarin.Forms controls. The API chosen for the sample
consists of
AccessibilityLabel– string property to add text for screen readers.InAccessibleTree– boolean that tells screen readers to 'skip' this control (when set tofalse).
These two properties were chosen as they are common across the different
platforms' accessibility APIs. The AccessbilityEffect class
implements the bindable properties and the code for adding them
to a control (platform-specific implementations for the effect
are required to make it work):
public static class AccessibilityEffect
{
public static readonly BindableProperty AccessibilityLabelProperty =
BindableProperty.CreateAttached("AccessibilityLabel",
typeof(string), typeof(AccessibilityEffect), "",
propertyChanged:OnAccessibilityLabelChanged);
public static readonly BindableProperty InAccessibleTreeProperty =
BindableProperty.CreateAttached("InAccessibleTree",
typeof(bool), typeof(AccessibilityEffect), true,
propertyChanged: OnInAccessibleTreeChanged);
// AccessibilityLabel
public static string GetAccessibilityLabel(BindableObject view)
{
return (string)view.GetValue (AccessibilityLabelProperty);
}
public static void SetAccessibilityLabel(BindableObject view, string value)
{
view.SetValue (AccessibilityLabelProperty, value);
}
static void OnAccessibilityLabelChanged(BindableObject bindable, object oldValue, object newValue)
{
var hasLabel = !string.IsNullOrEmpty(newValue as string);
AddRemoveEffect(bindable, hasLabel);
}
// InAccessibleTree
public static bool GetInAccessibleTree(BindableObject view)
{
return (bool)view.GetValue(InAccessibleTreeProperty);
}
public static void SetInAccessibleTree(BindableObject view, bool value)
{
view.SetValue(InAccessibleTreeProperty, value);
}
static void OnInAccessibleTreeChanged(BindableObject bindable, object oldValue, object newValue)
{
var add = newValue != null;
AddRemoveEffect(bindable, add);
}
// .. other properties
// helper method
static void AddRemoveEffect(BindableObject bindable, bool add)
{
var view = bindable as View;
if (view == null)
{
return;
}
if (add)
{
if (view.Effects.Count == 0)
{
// shortcut to add if there are none already
view.Effects.Add(new AddAccessibilityEffect());
}
else
{
// more expensive check to see if it exists before adding
var exists = view.Effects.First(e => e is AddAccessibilityEffect);
if (exists == null)
{
view.Effects.Add(new AddAccessibilityEffect());
}
}
}
else
{
var toRemove = view.Effects.FirstOrDefault(e => e is AddAccessibilityEffect);
if (toRemove != null)
{
view.Effects.Remove(toRemove);
}
}
}
public class AddAccessibilityEffect : RoutingEffect
{
// string identifier matches [assembly] attributes in the platform-specific projects
public AddAccessibilityEffect() : base("MyCompany.AddAccessibilityEffect")
{
}
}
}
Use in XAML
The C# code below shows a label and entry control. The label control is excluded from the accessibility tree (i.e. it will be ignored by screen readers) and the entry control is assigned an accessible label that would be read by a screen-reader:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:a="clr-namespace:MyApp;assembly=MyAppAssembly"
x:Class="MyApp.MyPageXaml"
Padding="20">
<StackLayout VerticalOptions="StartAndExpand">
<Label Text="Name"
a:AccessibilityEffect.InAccessibleTree="false" />
<Entry Text="{Binding Path=Name}" x:Name="nameEntry"
Placeholder="task name"
a:AccessibilityEffect.AccessibilityLabel="Todo item"
/>
</StackLayout>
</ContentPage>
Note: the effect can only be used in the XAML if a custom
xmlns is declared that creates a reference to the assembly containing
the effect. In this example, xmlns:a has been declared to reference
the local assembly, and the a: prefix is used to add the
effect attributes to XAML controls.
Use in C
The C# code below shows a label and an entry control. The label control is excluded from the accessibility tree (i.e. it will be ignored by screen readers) and the entry control is assigned an accessible label that would be read by a screen-reader:
var nameLabel = new Label { Text = "Name" };
var nameEntry = new Entry { StyleId = "TodoName", Placeholder="task name" };
nameEntry.SetBinding (Entry.TextProperty, "Name");
AccessibilityEffect.SetInAccessibleTree(nameLabel, false); // hide from screenreader
AccessibilityEffect.SetAccessibilityLabel(nameEntry, "Todo item"); // screenreader description
Android Platform-Specific Effect
The following class should be added to the Android application project. It
implements the effect API (AccessibilityLabel and InAccessibleTree) using
the native Android widget properties ContentDescription and Focusable
to provide an accessible UI.
The "MyCompany.AddAccessibilityEffect" string in the RoutingEffect subclass
matches the ResolutionGroupName and ExportEffect attributes – this is
how the effect is resolved and applied at runtime.
using System;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(AddAccessibilityEffect), "AddAccessibilityEffect")]
namespace MyApp
{
/// <summary>Add accessibility properties to Xamarin.Forms controls in Android</summary>
public class AddAccessibilityEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
Control.ContentDescription = AccessibilityEffect.GetAccessibilityLabel(Element);
Control.Focusable = AccessibilityEffect.GetInAccessibleTree(Element);
}
catch (Exception ex)
{
Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached()
{
}
protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
{
if (args.PropertyName == AccessibilityEffect.AccessibilityLabelProperty.PropertyName)
{
Control.ContentDescription = AccessibilityEffect.GetAccessibilityLabel(Element);
}
else if (args.PropertyName == AccessibilityEffect.InAccessibleTreeProperty.PropertyName)
{
Control.Focusable = AccessibilityEffect.GetInAccessibleTree(Element);
}
}
}
}
iOS Platform-Specific Effect
This class should be added to the iOS application project. It
implements the effect API (AccessibilityLabel and InAccessibleTree) using
the native iOS view properties AccessibilityLabel and IsAccessibilityElement
to provide an accessible UI.
The "MyCompany.AddAccessibilityEffect" string in the RoutingEffect subclass
matches the ResolutionGroupName and ExportEffect attributes – this is
how the effect is resolved and applied at runtime:
using System;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(AddAccessibilityEffect), "AddAccessibilityEffect")]
namespace MyApp
{
/// <summary>Add accessibility properties to Xamarin.Forms controls in iOS</summary>
public class AddAccessibilityEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
Control.AccessibilityLabel = AccessibilityEffect.GetAccessibilityLabel(Element);
// other properties
}
catch (Exception ex)
{
Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached()
{
}
protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
{
if (args.PropertyName == AccessibilityEffect.AccessibilityLabelProperty.PropertyName)
{
Control.AccessibilityLabel = AccessibilityEffect.GetAccessibilityLabel(Element);
}
else if (args.PropertyName == AccessibilityEffect.InAccessibleTreeProperty.PropertyName)
{
Control.IsAccessibilityElement = AccessibilityEffect.GetInAccessibleTree(Element);
}
// ... other properties
else
{
base.OnElementPropertyChanged(args);
}
}
}
}
Windows
Platform-specific implementations can also be written for Windows, Windows Phone, and UWP projects using the native accessibility APIs.
Summary
Xamarin.Forms does not currently support some accessibility APIs available in the underlying native frameworks. This guide includes sample code for a Xamarin.Forms effect to help developers build accessible user interfaces by setting the accessibility properties on the native controls.
Let us know how you feel about this
Translation Quality
0/250
Xamarin Workbook
If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.

