I am adding accessibility into my SwiftUI app, until I encountered a problem when adding an accessibilityLabel(_:)
to a Button
in a ToolbarItem
. Here is some sample code:
struct ContentView: View {
var body: some View {
NavigationView {
Text("Content")
.accessibilityElement()
.accessibilityLabel("Content label") // This is here just to show Voice Control is working
.navigationTitle("Test")
.toolbar {
// Comment parts out below, depending on what you want to test
ToolbarItem(placement: .navigationBarTrailing) {
// What I want, but doesn't work:
// (Also tried adding the label to either the button
// label or the whole button itself, neither works.)
Button {
print("Pressed")
} label: {
Image(systemName: "plus")
.accessibilityElement()
.accessibilityLabel("Some label")
}
.accessibilityElement()
.accessibilityLabel("Some other label")
// What I don't want, but does work:
Image(systemName: "plus")
.accessibilityLabel("Another label")
}
}
}
}
}
I am testing the accessibility with Voice Control. What is strange is that the accessibility label works for the image in the toolbar item, but not when inside a button in the toolbar item.
When I say the accessibility label doesn't work, it says "Add"
instead of the expected label. I assume SwiftUI creates this label by default for the system image "plus", but I would like to change it.
The button accessibility labels also work when not in a toolbar item. Is this a bug, or some issue I have caused?
SwiftUI treats single toolbar items differently (applies their own style, size etc). It looks like this applies to accessibility labels as well.
Fortunately, there is a workaround - see SwiftUI Xcode 12.3 can't change button size in toolbar.
In your case, the code should look like:
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
Text("")
.accessibilityHidden(true)
Button {
print("Pressed")
} label: {
Image(systemName: "plus")
.accessibilityElement()
.accessibilityLabel("Some label")
}
}
}
}
(accessibilityLabel
can be attached either to the Image
or to the Button
.)
Tested with Xcode 12.3, iOS 14.3.
My radar had 'Less than 10' similar reports, but is now actually fixed for iOS 15+. However, if you are supporting older versions, see the answer above by @pawello2222 and here is an updated version to only do the workaround if necessary:
/// Embeds the content in a view which removes some
/// default styling in toolbars, so accessibility works.
/// - Returns: Embedded content.
@ViewBuilder func embedToolbarContent() -> some View {
if #available(iOS 15, *) {
self
} else {
HStack(spacing: 0) {
Text("")
.frame(width: 0, height: 0)
.accessibilityHidden(true)
self
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With