【问题标题】:SwiftUI List only taps contentSwiftUI List 只点击内容
【发布时间】:2023-02-07 18:07:57
【问题描述】:

我在 SwiftUI 中有一个列表,我用自定义 SwiftUI 单元格填充,问题是点击时我需要做一些事情,并且只有当你点击单元格中的文本时点击才有效,如果你点击任何空白区域它不会工作。我怎样才能解决这个问题?

struct SelectDraftView: View {
    @Environment(\.presentationMode) var presentationMode

    @ObservedObject var viewModel = SelectDraftViewModel()
    
    var body: some View {
        VStack {
                List {
                    ForEach(viewModel.drafts.indices, id: \.self) { index in
                        DraftPostCell(draft: viewModel.drafts[index])
                            .contentShape(Rectangle())
                            .onTapGesture {
                                presentationMode.wrappedValue.dismiss()
                            }
                    }
                    .onDelete { indexSet in
                        guard let delete = indexSet.map({ viewModel.drafts[$0] }).first else { return }
                        viewModel.delete(draft: delete)
                    }
                
            }
                .background(Color.white)
            Spacer()

        }
    }
}

struct DraftPostCell: View {
    var draft: CDDraftPost
    
    var body: some View {

        VStack(alignment: .leading) {
            Text(draft.title ?? "")
                .frame(alignment: .leading)
                .font(Font(UIFont.uStadium.helvetica(ofSize: 14)))
                .padding(.bottom, 10)
            if let body = draft.body {
                Text(body)
                    .frame(alignment: .leading)
                    .multilineTextAlignment(.leading)
                    .frame(maxHeight: 40)
                    .font(Font(UIFont.uStadium.helvetica(ofSize: 14)))
            }
            Text(draft.date?.toString(format: "EEEE, MMM d, yyyy") ?? "")
                .frame(alignment: .leading)
                .font(Font(UIFont.uStadium.helvetica(ofSize: 12)))
        }
        .padding(.horizontal, 16)
    }
}

【问题讨论】:

    标签: ios swift swiftui swiftui-ontapgesture


    【解决方案1】:

    尝试在 DraftPostCell(...) 之后添加 .frame(idealWidth: .infinity, maxWidth: .infinity)。如果需要,您也可以使用 minWidth:

    EDIT-1:我用于测试的代码(在真实设备 ios 15.6、macCatalyst 上,而不是预览版):

    import Foundation
    import SwiftUI
    
    
    struct ContentView: View {
        var body: some View {
            SelectDraftView()
        }
    }
    
    class SelectDraftViewModel: ObservableObject {
        @Published var drafts: [
            CDDraftPost] = [
                CDDraftPost(title: "item 1", date: Date(), body: "body 1"),
                CDDraftPost(title: "item 2", date: Date(), body: "body 4"),
                CDDraftPost(title: "item 3", date: Date(), body: "body 3")]
        
        func delete(draft: CDDraftPost) {  }
    }
    
    struct CDDraftPost: Codable {
        var title: String?
        var date: Date?
        var body: String?
    }
    
    struct SelectDraftView: View {
        @Environment(.presentationMode) var presentationMode
        
        @ObservedObject var viewModel = SelectDraftViewModel()
        
        var body: some View {
            VStack {
                List {
                    ForEach(viewModel.drafts.indices, id: .self) { index in
                        DraftPostCell(draft: viewModel.drafts[index])
                            .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
                            .contentShape(Rectangle())
                            .border(.red)  // <-- for testing
                            .onTapGesture {
                                print("----> onTapGesture")
                                //  presentationMode.wrappedValue.dismiss()
                            }
                    }
                    .onDelete { indexSet in
                        guard let delete = indexSet.map({ viewModel.drafts[$0] }).first else { return }
                        viewModel.delete(draft: delete)
                    }
                }
                .background(Color.white)
                Spacer()
                
            }
        }
    }
    
    struct DraftPostCell: View {
        var draft: CDDraftPost
        
        var body: some View {
            VStack(alignment: .leading) {
                Text(draft.title ?? "")
                    .frame(alignment: .leading)
                //    .font(Font(UIFont.uStadium.helvetica(ofSize: 14)))
                    .padding(.bottom, 10)
                if let body = draft.body {
                    Text(body)
                        .frame(alignment: .leading)
                        .multilineTextAlignment(.leading)
                        .frame(maxHeight: 40)
                    //   .font(Font(UIFont.uStadium.helvetica(ofSize: 14)))
                }
                Text(draft.date?.formatted() ?? "")
                    .frame(alignment: .leading)
                //  .font(Font(UIFont.uStadium.helvetica(ofSize: 12)))
            }
            .padding(.horizontal, 16)
        }
    }
    

    【讨论】:

    • 这没有用,它还将所有内容推送到中心,这并不理想
    • 奇怪,对我来说效果很好。您是否将 SelectDraftView 嵌入到您未向我们展示的其他代码中?在我的测试中,我只是把它单独放在ContentView 中。
    • 不,它只是在具有内容形状和点击的 ForEach 内部
    • 我将使用我用于测试的代码更新我的答案。请注意,为避免居中,只需将 , alignment: .leading 添加到框架中即可。
    • 你是说你在另一个 ForEach 循环中有 SelectDraftView 吗?
    【解决方案2】:

    我可能迟到了,但这对将来检查此内容的任何人都有用。 在执行 .onTapGesture{...} 之前,您需要在视图中添加 .background() 修饰符

    所以在你的ForEach代码中会被修改成这样:

    ForEach(viewModel.drafts.indices, id: .self) { index in
        DraftPostCell(draft: viewModel.drafts[index])
            .contentShape(Rectangle())
            .frame(maxWidth: .infinity) // you should use the frame parameter according to your needs, but if you want your cell to occupy the whole width of your scroll view, use this one
            .background()  // this makes the empty portions of view 'non-transparent', so those portions also receive the tap gesture
            .onTapGesture {
                presentationMode.wrappedValue.dismiss()
            }
    }
    

    P.S 如果您需要滚动视图单元格的整个部分来接收点击手势,您还需要添加 .frame(...) 修饰符,因此它具有您想要的确切背景

    【讨论】:

      猜你喜欢
      • 2021-10-31
      • 2020-11-12
      • 2021-07-15
      • 1970-01-01
      • 1970-01-01
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多