SwiftUI列表禁用单元格点击

16

我正在使用带有SwiftUI的xCode 11 beta 7。

我有一个简单的列表,每个列表元素都有几个按钮。目前,当用户按下单元格(而不是按钮)时,它会突出显示列表单元格的后面(可能不是SwiftUI的正确术语)。

如何禁用此行为?我找不到明显的API来禁用它。

List {
    HStack {
        Group {
            Button(action: {}) {
                Text("Read").padding(5)
            }.onTapGesture {
                print("1")                    
            }
            .padding()
            .background(Color.blue)
            .cornerRadius(5)
        }
        Group {
            Button(action: {}) {
                Text("Notify").padding(5)
            }.onTapGesture {
                print("2") 
            }
            .padding()
            .background(Color.purple)
            .cornerRadius(5)
        }
        Group {
            Button(action: {}) {
                Text("Write").padding(5)
            }.onTapGesture {
                print("3")
            }
            .padding()
            .background(Color.yellow)
            .cornerRadius(5)
        }
    }
}

你目前无法直接禁用单元格的高亮显示。但是你可以使用垂直scrollView代替列表。此外,你可以设置一个背景来阻止用户看到高亮的背景,但分隔符仍会闪烁。 - Mojtaba Hosseini
是的,我感觉这可能是现在的解决方案,SwiftUI 当然还不够成熟。 - Reedy
你需要帮忙吗? - Mojtaba Hosseini
我有两个感谢。 - Reedy
注意事项:List(...)处理大型列表的性能比ScrollView(...)更好,因此如果有这样的情况,请找到一种处理列表项点击事件的方法,放弃使用滚动条。 - ChrisH
3个回答

38

How to remove highlight on tap of List with SwiftUI? 中的答案相同。

虽然我来晚了,但这是为那些像我一样在寻找答案的人准备的

我的发现

我想你应该看看这篇短文:如何禁用 Button 和 NavigationLink 中图像的叠加颜色,它来自于 @TwoStraws

只需将 .buttonStyle(PlainButtonStyle()) 修改器添加到你的 List 中的项目中,你就会得到你想要的效果。它还可以使 List 中的 Button 再次起作用,这也是我遇到的另一个问题。

Swift 5.1 的工作示例:

import Combine
import SwiftUI

struct YourItem: Identifiable {
    let id = UUID()
    let text: String
}

class YourDataSource: ObservableObject {
    let willChange = PassthroughSubject<Void, Never>()
    var items = [YourItem]()

    init() {
        items = [
            YourItem(text: "Some text"),
            YourItem(text: "Some other text")
        ]
    }
}

struct YourItemView: View {
    var item: YourItem

    var body: some View {
        VStack(alignment: .leading) {
            Text(item.text)
            HStack {
                Button(action: {
                    print("Like")
                }) {
                    Image(systemName: "heart.fill")
                }
                Button(action: {
                    print("Star")
                }) {
                    Image(systemName: "star.fill")
                }
            }
        }
        .buttonStyle(PlainButtonStyle())
    }
}

struct YourListView: View {
    @ObservedObject var dataSource = YourDataSource()

    var body: some View {
        List(dataSource.items) { item in
            YourItemView(item: item)
        }
        .navigationBarTitle("List example", displayMode: .inline)
        .edgesIgnoringSafeArea(.bottom)
    }
}

#if DEBUG
struct YourListView_Previews: PreviewProvider {
    static var previews: some View {
        YourListView()
    }
}
#endif

正如文章所述,它也适用于NavigationLink。我希望它能帮助到一些人。


1
很好的答案。我想补充一点,如果你将 .buttonStyle(PlainButtonStyle()) 移出 YourItemView 结构体本身,并将其放置在 YourListView 结构体中,在 YourItemView(item: item) 代码行之后,这似乎也可以工作。 - Rillieux
太棒了,它工作得十分顺畅。 - Li Jin
非常好的答案,感谢! - krlbsk

9

这是我最简单的解决方案,并且对我有效(惊奇吧,我正在使用Swift和SwiftUI构建我的第一个应用程序,同时这也是我在SO上的第一篇帖子):

无论您在哪里使用按钮,请添加.buttonStyle(BorderlessButtonStyle())

Button(action:{}){
Text("Hello")
}.buttonStyle(BorderlessButtonStyle())

然后在你的列表中添加 .onTapGesture {return}

List{
Text("Hello")
}.onTapGesture {return}

我在其中一个部分中使用了段落视图点击手势,但现在已经被禁用了。 - Ahmadreza

0

不要使用按钮,改用手势

Group {
    Text("Notify").padding(5).gesture(TapGesture().onEnded() {
            print("action2")
            })
        .padding()
        .background(Color.purple)
        .cornerRadius(5)
    }

1
这样做失去了按钮的意义,而且您也无法获得免费提供的漂亮按钮动画,例如触摸时的高亮显示等。 - Reedy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接