使用按钮点击列表中的某行时,即使在按钮区域外单击也会触发操作

On tap some row in List with a button the action is triggered even clicking outside the button area

我正在创建一个包含自定义组件列表的主屏幕。这些组件是一个或多个带有导航link或按钮的点击区域,如上图:

App Home

但是不考虑点击区域,如果我点击行中的任何 space,即使它在 button/navigation link 区域之外也会触发点击

Click buttom area

Click bug video

代码在 https://github.com/isaquedev/swiftui-list-click-bug 和下面可用:

首页

import SwiftUI

struct ContentView: View {

    var items: [HomeSection] = [
        HomeSection(title: "Mais próximos", type: .nearest),
        HomeSection(title: "", type: .list, items: [
            SectionItem(title: "Românticos", cover: "prato-1"),
            SectionItem(title: "Especiais", cover: "prato-2"),
            SectionItem(title: "Agradáveis", cover: "prato-1"),
            SectionItem(title: "Interessantes", cover: "prato-2"),
        ])
    ]

    var body: some View {
        VList {
            ForEach(items) { item in
                switch item.type {
                case .nearest:
                    NearestCell(title: item.title)
                case .list:
                    ListCell(items: item.items ?? [])
                }
            }
        }
    }
}

VList

import SwiftUI

struct VList<Content:View>: View {
    
    var content: () -> Content
    
    var body: some View {
        if #available(iOS 14.0, *) {
            ScrollView {
                LazyVStack(spacing: 0) {
                    content()
                }
            }
        } else {
            List {
                content()
                .padding(.horizontal, -20)
            }
            .onAppear {
                UITableView.appearance().separatorStyle = .none
                UITableViewCell.appearance().selectionStyle = .none
            }
        }
    }
}

最近的小区

import SwiftUI

struct NearestCell: View {
    
    var title: String
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(title)
                .font(.title)
                .padding(.bottom, 16)
            
            VStack {
                Text("Veja restaurantes a sua volta")
                
                Button(action: {
                    print("Click")
                }, label: {
                    Text("Visualizar")
                })
                .padding(.top, 16)
            }
            .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .center)
            .padding(.vertical, 16)
            .overlay(
                RoundedRectangle(cornerRadius: 12)
                    .stroke(Color.black, lineWidth: 1)
            )
        }
        .padding(.all, 16)
        .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
    }
}

列表单元格

import SwiftUI

struct ListCell: View {
    
    var items: [SectionItem]
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Categorias")
                .font(.title)
            
            ScrollView(.vertical, showsIndicators: false) {
                HStack {
                    ForEach(items) { item in
                        VStack {
                            Image(item.cover)
                                .resizable()
                                .scaledToFill()
                                .frame(width: 80, height: 80, alignment: .center)
                                .clipped()

                            Text(item.title)
                        }
                    }
                }
            }
            .frame(height: 113)
        }
        .padding(.all, 16)
    }
}

主页部分

enum HomeSectionType {
    
    case nearest, list
    
}

class HomeSection: Identifiable {
    
    let id = UUID()
    var title: String
    var type: HomeSectionType
    var items: [SectionItem]?
    
    init(title: String, type: HomeSectionType, items: [SectionItem]? = nil) {
        self.title = title
        self.type = type
        self.items = items
    }
    
}

节项

class SectionItem: Identifiable {
    
    let id = UUID()
    var title: String
    var cover: String

    init(title: String, cover: String) {
        self.title = title
        self.cover = cover
    }
    
}

你的代码没有问题,都是因为ListList apply action of a Button of a row of a Button to all row,解决问题使用只需 Text 并将操作代码放入 onTapGesture.

    struct NearestCell: View {
    
    var title: String
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(title)
                .font(.title)
                .padding(.bottom, 16)
            
            VStack {
                
                
                Text("Veja restaurantes a sua volta")
                
                Text("Visualizar")                      // <<: here
                    .foregroundColor(Color.blue)
                    .padding(.top, 16)
                    .onTapGesture { print("Click") }    // <<: here
                
                
            }
            .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .center)
            .padding(.vertical, 16)
            .overlay(
                RoundedRectangle(cornerRadius: 12)
                    .stroke(Color.black, lineWidth: 1)
            )
        }
        .padding(.all, 16)
        .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
    }
}