iOS Accessibility Tutorial: Making Custom Controls Accessible

In this iOS accessibility tutorial, you’ll learn to make custom controls accessible using VoiceOver, elements group, custom action, traits, frame and more. By Andrew Tetlaw.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Overriding Accessibility Value

The VoiceOver announcement implementation for the knob rating’s value is simple: You need to override the accessibilityValue property. You can override this property in your subclass.

Add the following code to RatingKnobAccessibilityElement:

override var accessibilityValue: String? {
  get {
    guard let rating = ratingViewController?.rating else {
      return super.accessibilityValue
    }

    return "\(rating)"
  }

  set {
    super.accessibilityValue = newValue
  }
}

Build and run. VoiceOver should now announce the rating value as you adjust it.

Accessibility Frame in Container Space

With Screen Curtain disabled, you may notice that as you switch focus to your custom element there’s no frame drawn around it. You need to override accessibilityFrameInContainerSpace to fix that.

First, in AddRatingViewController, add the following code:

var frameForAccessibilityElement: CGRect {
  return ratingKnobContainer.convert(ratingKnob.frame, to: nil)
}

The code above converts the knob’s frame to the coordinate space of the accessibility container or view controller’s view. You must do this because the knob is nested within another view. This will allow the accessibility focus frame to correctly position in the view controller’s view.

Then, override the following property in RatingKnobAccessibilityElement:

override var accessibilityFrameInContainerSpace: CGRect {
  get {
    guard let frame = ratingViewController?.frameForAccessibilityElement 
      else {
        return super.accessibilityFrameInContainerSpace
    }

    return frame
  }

  set {
    super.accessibilityFrameInContainerSpace = newValue
  }
}

Build and run. Then, add a rating. Swipe to select the knob control. The frame should correctly surround the control.

Frame for selected knob

Supporting Reduced Motion

Since the knob control can animate into its next position, you can add support for the accessibility reduce motion feature, too. You’ll normally make use of this feature if your end users have sensitivity to motion effects or screen movement.

First, open Knob.swift.

In the class KnobRenderer find setPointerAngle(_:animated:), then replace:

if animated {

With:

if animated && !UIAccessibility.isReduceMotionEnabled {

In the if statement, you decide whether to animate the knob rotation based on the device’s reduced motion accessibility setting.

To test this out, you need to go to your device’s accessibility settings and set Reduce Motion to On. You find this setting under Accessibility ▸ Motion.

Build and run. Now, navigate between amps. You should see the knob value change without the knob rotation animation.

Taking Accessibility to the Next Level

Now, add an amp rating and make it an eleven. Seems a bit anticlimactic right?

If an amp deserves the ultimate rating, the app should acknowledge this in some way.

Inside AddRatingViewController.swift, go to RatingKnobAccessibilityElement and add the following to the end of accessibilityIncrement():

if let rating = ratingViewController?.rating, rating == 11 {
  let message = NSAttributedString(
    string: "Whoa! This one goes to 11!",
    attributes: [.accessibilitySpeechPitch: 0.1,
                 .accessibilitySpeechQueueAnnouncement: true])
  UIAccessibility.post(notification: .announcement,
                       argument: message)
}

UIAccessibility.Notification.announcement is an accessibility notification you can use to make VoiceOver announce something. I suppose the name makes that obvious. You can pass an NSAttributedString annotated with special attributes for VoiceOver.

accessibilitySpeechPitch controls the pitch of the voice. It’s a value between 0.0 and 2.0. 1.0 is normal, 0.0 is the lowest pitch and 2.0 is the highest.

accessibilitySpeechQueueAnnouncement controls when the string is announced. Specify true to ensure VoiceOver queues the announcement after it finishes other current announcements.

If this is false, the notification can interrupt whatever VoiceOver is announcing when the app posts this notification. You don’t want to interrupt the value original announcement, but rather add this as a fun VoiceOver Easter egg when your user selects 11 on the rating knob.

Build and run. Try it out. Hopefully, it’ll be a fun surprise. :)

Note: There are many more attributed string accessibility attributes to explore. Have a look at them all in Apple’s documentation.

And that’s it! You now have an app that’s accessible. Navigating the app is a simple and clear experience, and it even includes an Easter egg for those using VoiceOver!

Great job! :]

Where to Go From Here?

You can download the final project using the Download Materials button at the top or bottom of this tutorial.

Of course, this is not the limit of what you can achieve with the iOS accessibility features. Here’s a couple of challenges you may like to try:

Implement accessibilityPerformMagicTap():
Magic tap is a special accessibility gesture that should act as a shortcut to the most likely action. For example, if there’s an incoming phone call, the magic tap will answer the call and then hang up if you perform the gesture again. Perhaps for your app, you might use it to trigger adding a rating or view the next amp.

Implement accessibilityPerformEscape():
This is another standard gesture for dismissing the current modal view on screen. This could be useful for dismissing AmpDetailsViewController.

Finally, start exploring. The iOS Accessibility features are extensive. Implementing any number of them will instantly elevate your app above all the apps that fail to consider them.

Apple’s documentation is a gold mine for ideas on improving the accessibility of your app. And, a great place to start is the Apple Accessibility Documentation.

I hope you enjoyed this iOS accessibility tutorial. If you have any questions or comments, please join the forum discussion below.