SwiftUI无法使用HStack的Spacer

Qui*_*inn 7 ios swift swiftui

我有一个列表视图,列表的每一行都包含一个带有某些文本视图和图像的HStack,如下所示:

HStack{
    Text(group.name)
    Spacer()
    if (groupModel.required) { Text("Required").color(Color.gray) }
    Image("ic_collapse").renderingMode(.template).rotationEffect(Angle(degrees: 90)).foregroundColor(Color.gray)
}.tapAction { self.groupSelected(self.group) }
Run Code Online (Sandbox Code Playgroud)

这似乎很好用,除了当我在文本和图像之间的空白区域(Spacer()是)轻拍时,tap动作未注册。仅当我在文本或图像上点击时,才会发生点击动作。

其他人是否遇到过此问题/知道解决方法?

小智 18

在我看来,出于可访问性的原因,最好的方法是将标签包裹在标签HStack内部Button,为了解决Spacer无法点击的问题,您可以.contentShape(Rectangle())HStack.

所以根据你的代码将是:

Button {
    self.groupSelected(self.group)
} label: {
    HStack {
        Text(group.name)
        Spacer()
        if (groupModel.required) {
            Text("Required").color(Color.gray)
        }
        Image("ic_collapse")
            .renderingMode(.template)
            .rotationEffect(Angle(degrees: 90))
            .foregroundColor(Color.gray)
    }
    .contentShape(Rectangle())
}
Run Code Online (Sandbox Code Playgroud)


rob*_*off 16

为什么不直接使用Button?

Button(action: { self.groupSelected(self.group) }) {
    HStack {
        Text(group.name)
        Spacer()
        if (groupModel.required) { Text("Required").color(Color.gray) }
        Image("ic_collapse").renderingMode(.template).rotationEffect(Angle(degrees: 90)).foregroundColor(Color.gray)
    }
}.foregroundColor(.primary)
Run Code Online (Sandbox Code Playgroud)

如果您不希望按钮将强调色应用于Text(group.name),则必须foregroundColor像我在示例中所做的那样设置。


hnh*_*hnh 7

据我最近了解,还有:

HStack {
  ...
}
.contentShape(Rectangle())
.onTapGesture { ... }
Run Code Online (Sandbox Code Playgroud)

对我来说效果很好。

  • 事实上,需要这个解决方案让我对 SwiftUI 总体感到失望。无论如何,这是一个很好的解决方案! (6认同)
  • Hacking With Swift 的更多解释:https://www.hackingwithswift.com/quick-start/swiftui/how-to-control-the-tappable-area-of-a-view-using-contentshape。 (2认同)

Asi*_*ati 7

在每个视图上都像魔术一样工作:

extension View {
        func onTapGestureForced(count: Int = 1, perform action: @escaping () -> Void) -> some View {
            self
                .contentShape(Rectangle())
                .onTapGesture(count:count, perform:action)
        }
    }
Run Code Online (Sandbox Code Playgroud)


Jim*_*rdt 6

我已经能够通过将 Spacer 包裹在 ZStack 中并添加具有非常低不透明度的纯色来解决此问题:

ZStack {
    Color.black.opacity(0.001)
    Spacer()
}
Run Code Online (Sandbox Code Playgroud)


Cas*_*gen 6

基于吉姆回答的简单扩展

extension Spacer {
    /// /sf/answers/4019173231/
    public func onTapGesture(count: Int = 1, perform action: @escaping () -> Void) -> some View {
        ZStack {
            Color.black.opacity(0.001).onTapGesture(count: count, perform: action)
            self
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在这有效

Spacer().onTapGesture {
    // do something
}
Run Code Online (Sandbox Code Playgroud)