为 SwiftUI Widget intent 按钮添加 buttonStyle 会搞砸 VoiceOver

Adding buttonStyle for SwiftUI Widget intent button messes up VoiceOver

提问人:Samps 提问时间:11/10/2023 更新时间:11/10/2023 访问量:26

问:

在 SwiftUI Interactive Widget(iOS 17)中,当您添加:

Button(intent: callWidgetIntent) {
    HStack {
        Image(systemName: "eye.fill")
        Text("Update")
    }
}
.buttonStyle(.plain)

它会搞砸 VoiceOver。读出无法发音的操作将导致应用,而不是调用 intent。它可以是任何 buttonStyle - 而不仅仅是 .plain。 此外,添加 accessibilityLabel 也无济于事。 当我删除 buttonStyle 时,VoiceOver 就会起作用。

知道为什么或如何解决它吗? 一种方法是删除样式并添加 tint(.clear) 以删除按钮背景:

Button(intent: callWidgetIntent) {
    HStack {
        Image(systemName: "eye.fill")
        Text("Update")
    }
    .foregroundColor(.white)
}
.tint(.clear)
.accessibilityElement(children: .ignore)
.accessibilityLabel("Update")

但在这种情况下,按钮有一些奇怪的填充。需要在不引入一些神奇的负数进行填充的情况下将其删除

iOS SwiftUI 小部件 画外音 iOS17

评论


答:

0赞 Samps 11/24/2023 #1

通过为小部件创建自定义 ButtonStyle 解决了该问题。 最重要的是 minWidth 和 minHeight 大于内容大小。 然后它需要有 .accessibilityElement(children: .ignore) 或 .accessibilityElement() 并设置 accessibilityLabel。 不是最好的解决方案,也不是很有活力,但还没有找到更好的解决方案

所以它看起来像:

public struct WidgetButtonStyle: ButtonStyle {
    public func makeBody(configuration: Configuration) -> some View {
        configuration
            .label
            .tint(.clear)
            // minSize needs to be bigger than content
            .frame(minWidth: 30, minHeight: 30)
            // This is also needed to make VoiceOver work correctly
            .accessibilityElement()
            // Could add accessibilityLabel here also, but I decided to do it outside
    }
}

// Using it:
Button(
    "My button",
    action: {}
)
.buttonStyle(WidgetButtonStyle())
.accessibilityLabel("My button")