SwiftUI:自定义按钮无法识别具有清晰背景和 buttonStyle 的触摸

SwiftUI: Custom button does not recognize touch with clear background and buttonStyle

我在 SwiftUI 中偶然发现 Buttons 与自定义 ButtonStyle.

相结合的奇怪行为

我的目标是用某种 'push-back animation' 创建自定义 ButtonStyle。我为此使用了以下设置:

struct CustomButton<Content: View>: View {
    private let content: () -> Content

    init(content: @escaping () -> Content) {
        self.content = content
    }

    var body: some View {
        VStack {
            Button(action: { ... }) {
                content()
            }
            .buttonStyle(PushBackButtonStyle(pushBackScale: 0.9))
        }
    }
}

private struct PushBackButtonStyle: ButtonStyle {
    let pushBackScale: CGFloat

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration
            .label
            .scaleEffect(configuration.isPressed ? pushBackScale : 1.0)
    }
}

// Preview
struct Playground_Previews: PreviewProvider {
    static var previews: some View {
        CustomButton {
            VStack(spacing: 10) {
                HStack {
                    Text("Button Text").background(Color.orange)
                }

                Divider()

                HStack {
                    Text("Detail Text").background(Color.orange)
                }
            }
        }
        .background(Color.red)
    }
}

当我现在尝试在 Text 视图之外触摸此按钮时,什么也不会发生。不会显示任何动画,也不会调用操作块。

到目前为止我发现了什么:

现在的问题是,是否有人对如何正确解决这个问题或如何修复它有更好的想法?

只需使用 .frame 就可以了。 为了使其易于测试,我将其重写为:

struct CustomButton: View {

    var body: some View {
                    Button(action: {  }) {
        VStack(spacing: 10) {
            HStack {
                Text("Button Text").background(Color.orange)
                .frame(minWidth: 0, maxWidth: .infinity)
                .background(Color.orange)
            }

            Divider()

            HStack {
                Text("Detail Text").background(Color.orange)
                .frame(minWidth: 0, maxWidth: .infinity)
                .background(Color.orange)
            }
                        }
    }
        .buttonStyle(PushBackButtonStyle(pushBackScale: 0.9))
    }
}

private struct PushBackButtonStyle: ButtonStyle {
    let pushBackScale: CGFloat

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration
            .label
            .scaleEffect(configuration.isPressed ? pushBackScale : 1.0)
    }
}

希望能帮到你。 :-)

@用视频编辑。

只需在自定义按钮样式中添加命中测试内容形状,如下所示

测试 Xcode 11.4 / iOS 13.4

private struct PushBackButtonStyle: ButtonStyle {
    let pushBackScale: CGFloat

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration
            .label
            .contentShape(Rectangle())     // << fix !!
            .scaleEffect(configuration.isPressed ? pushBackScale : 1.0)
    }
}