如何限制 HStack 中的可点击区域以仅使删除按钮可点击

问题描述 投票:0回答:2

在我的 ListView 中,有一个由复选框、文本、间隔符和删除按钮组成的 HStack。不幸的是,单击 HStack 的任何部分(复选框/文本/空格区域)会导致删除按钮操作触发。如何限制此删除操作仅适用于删除按钮,而不适用于 SwiftUI ListView 中的整个 HStack 视图?

extension View {
    @ViewBuilder public func hidden(_ shouldHide: Bool) -> some View {
        switch shouldHide {
        case true: self.hidden()
        case false: self
        }
    }
}

struct AgendaItem: Identifiable {
    let id = UUID()
    var title: String
    var isSelected = false
}

struct AgendaList: View {
    @State private var agendaItems = [AgendaItem]()
    @State private var newAgendaItem = ""
    
    var body: some View {
        VStack {
            Text("Agenda List")
                .font(.title)
            
            HStack {
                ZStack(alignment: .topLeading) {
                    TextEditor(text: $newAgendaItem)
                        .frame(height: 40)
                        .overlay(
                            RoundedRectangle(cornerRadius: 3)
                                .stroke(Color(UIColor.opaqueSeparator), lineWidth: 0.5)
                        )
                    Text("Add agenda")
                        .fontWeight(.light)
                        .foregroundColor(.black.opacity(0.25))
                        .padding(8)
                        .hidden(!newAgendaItem.isEmpty)
                }
                
                Button(action: addItem) {
                    Text("Add")
                }
                .padding(.horizontal)
            }
            .padding()
            
            List(agendaItems) { agendaItem in
                HStack(alignment: .top, spacing: 8) {
                    VStack {
                        CheckBox(isChecked: $agendaItems[getIndex(for: agendaItem.id)].isSelected)
                            .padding(.top, 3)
                        Spacer()
                    }
                    Text(agendaItem.title)
                        .strikethrough(agendaItem.isSelected)
                    Spacer()
                    Button(action: {
                        deleteItem(at: getIndex(for: agendaItem.id))
                    }) {
                        Image(systemName: "trash")
                    }
                }
            }
            .listRowBackground(Color.red)
        }
    }
    
    func addItem() {
        agendaItems.append(AgendaItem(title: newAgendaItem))
        newAgendaItem = ""
    }
    
    func getIndex(for id: UUID) -> Int {
        return agendaItems.firstIndex { $0.id == id } ?? 0
    }
    
    func deleteItem(at index: Int) {
        agendaItems.remove(at: index)
    }
}

struct CheckBox: View {
    @Binding var isChecked: Bool
    
    var body: some View {
        Button(action: {
            isChecked.toggle()
        }) {
            Image(systemName: isChecked ? "checkmark.square.fill" : "square")
                .foregroundColor(isChecked ? .blue : .gray)
        }
    }
}
swift swiftui swiftui-list tap hstack
2个回答
1
投票

您可以通过为按钮添加以下两个属性来实现此目的:

Button(action: {
    deleteItem(at: getIndex(for: agendaItem.id))
}) {
    Image(systemName: "trash")
}
.onTapGesture { }
.buttonStyle(BorderlessButtonStyle())

Button 视图的 buttonStyle 属性设置为 BorderlessButtonStyle 以移除按钮的背景。将 onTapGesture 修饰符添加到 Button 视图以处理点击事件,并为 onTapGesture 修饰符提供一个空闭包以防止列表行被点击。


0
投票

您可以通过将

.buttonStyle(...)
添加到
Button
内的
HStack
来实现所需的行为。

struct ContentView: View {
    var items = ["Item 1", "Item 2", "Item 3"]

    var body: some View {
        List(items, id: \.self) { item in
            HStack {
                Text(item)
                Spacer()
                Button("click me") {
                    print("\(item) button tapped")
                }
                .buttonStyle(.borderless)
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.