Search code examples
swiftswiftuiaccessibilityvoice-control

Accessibility of Image in Button in ToolbarItem


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?


Solution

  • 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.