Adding accessibility improvements to the emoji picker.

In part one I described how I started building my own SwiftUI emoji picker. This is a quick post about how I made some improvements to it regarding accessibility. Standard disclosure that I’m not saying this is the best way to do things. This is just what I came up with as a hobbyist trying to learn!

Those aren’t buttons!

With the way I built it the emojis displayed aren’t buttons. They’re just strings being displayed. When the user taps an emoji the picker is dismissed and the selection is remembered.

Text(oneEmoji.char)
    .font(.largeTitle)
    .onTapGesture(count: 1, perform: {
        emojiSelected = oneEmoji.char
        dismiss()
    })

I wasn’t sure how to handle this with VoiceOver and I had a feeling that what I was doing was way too “chatty”.

The iOS community is so helpful, and this time was no exception. I got some great feedback from Amro Mousa and Sommer Panage, two great engineers you should be following if you’re not already doing so!

Amro pointed out that even thought the emojis displayed are not buttons you can add accessibility traits that indicate that they act like buttons. According to Sommer that trait along with the selected trait removes the need for such a verbose hint.

Here’s what it looks like in code:

Text(oneEmoji.char)
    .font(.largeTitle)
    .onTapGesture(count: 1, perform: {
        emojiSelected = oneEmoji.char
        dismiss()
    })
    .accessibilityAddTraits([.isButton, .isSelected])
    .accessibilityLabel(Text("\(oneEmoji.name)"))
    .accessibilityHint(Text("Choose emoji."))

Now when you touch a lemon, for example, VoiceOver reads “Selected, lemon, button, choose emoji.” Much more concise and to the point!

Testing with with VoiceOver

It’s important to test drive all parts of your app when you’re trying to add support for VoiceOver. I quickly realized that I had a problem. When I touched any emoji on the bottom row the emoji was not selected. Instead I heard VoiceOver say “horizontal scroll bar” along with a description of how much content (pages of emojis) you could scroll through.

Instead of an emoji being selected the horizontal scrollbar is selected.

I got around this by adding some padding to the content the ScrollView is displaying.

.padding(.vertical, 20) // voiceover wouldn't let you select an emoji in the bottom row

An apple emoji on the bottom row is selected.

For users that aren’t using VoiceOver this change is barely noticeable. But that little bit of padding means that now an emoji on the bottom row can be selected without issue. I’m curious if this was the “correct” way to fix this problem. Always open to feedback!

PRO TIP

There’s a fast way to turn off VoiceOver when you’re done testing with it. Just ask Siri to turn it off!

Conclusion

Adding accessibility features to your app is incredibly important. Hopefully this can help you with that in the future.

If this post was helpful to you I’d love to hear about it! Find me on Twitter.