Issues with making UITabBar accessible
TL;DR if you have a UITabBar
which buttons don’t have titles, the only way to set an accessibility label is to use a dirty hack to actually set the title and hide it.
One of my clients has an app with a tabbed navigation, and the icons in the tab bar don’t have titles. So far so good, but to run the acceptance tests I need accessibility labels in order to locate the elements to tap.
To complicate the things the UITabBarController
comes form a Storyboard.
The things I tried:
- Storyboard - failed
- UIApparence - failed
UITabBarItem
- failed- Subclassing
Storyboard
There is no option in the Storyboard to set the accessibility label of the tab bar items.
UIApparence
If you inspect a tab bar in Reveal you’ll notice the buttons are no usual buttons, but UITabBarButton
instances. This is as far as I can tell a private class, and therefore we cannot directly access it, nor set values using the UIApparence
protocol.
I decided to drill down in the hierarchy, and to use UIApparence
on the UILabel
.
[UILabel appearanceWhenContainedIn:[[UITabBar class], nil] setTextColor:[UIColor clearColor]];
Both this, other combinations of UI components, and using tintColor
instead, either fail or result in funny behaviours, like the button starting without title, then adding a title when tapped, then keeping the button when another button is tapped.
UITabBarItem
I then tried to set the accessibilityLabel
value of the UITabBarItem
that the framework uses to configure the view. This failed as well.
Subclassing and hacking the view
I finally settled for this dirty hack: the bar button have a title, but it’s pushed off screen so that only Voice Over and my acceptance tests know that it’s there.
The way I’m doing it is by looping on all the buttons in the awakeFromNib
method of a UITabBarController
class made for the occasion, and the reason for that is that it comes from a Storyboard.
- (void)awakeFromNib {
[super awakeFromNib];
[self hideItemTitles];
}
- (void)hideItemTitles {
[self.tabBar.items enumerateObjectsUsingBlock:^(UITabBarItem *item, NSUInteger idx, BOOL *stop) {
item.titlePositionAdjustment = UIOffsetMake(0, 1000);
}];
}
I’m quite surprised by the state of accessibility in UITabBar
a UIKit component that has been there form the start.
Food for thoughts
- Do more experiments in order to find a nicer way to hide the title in the bar button
- Do more experiments in order to see if using the
UITabBarItems
is actually an option - What would happen if there was no Storyboard configuring the view? Would it be possible, or at least simpler, to set accessibility?