首页 > 解决方案 > 如何在不禁用列表项命中测试的情况下启用对列表项的选择?

问题描述

我正在尝试创建一个文件浏览器,用户可以在其中将我的 LibraryView 中的条目拖放到主视图上以显示它们。同样有效的是上下文菜单,用户可以在其中右键单击以删除或编辑文件上的首选项。问题是,如果我在文件的文本标签上禁用命中测试,我无法拖放文件,但选择有效...如果我启用命中测试,我无法单击文件的文本标签选择它。这是我的代码,任何帮助将不胜感激......

struct LibraryView: View {
    @ObservedObject var viewModel = LibraryViewModel()
    var body: some View {
        List(selection: $viewModel.selectedNodes) {
            ForEach(viewModel.nodes, id: \.self) { node in
                if let childrenNodes = node.childrenValues, childrenNodes.count > 0 {
                    Section(header: Text(node.displayName)) {
                        ForEach(childrenNodes, id: \.self) { childNode in
                            LibraryNodeChildView(node: childNode).contextMenu {
                                Button(action:{
                                    store.dispatch(LibraryAction.removeNode(childNode))
                                    store.dispatch(LibraryThunkCreatorImpl().persistLibraryState())
                                }){
                                    HStack {
                                        Text("Delete")
                                        Image(systemName: "trash")
                                    }
                                }
                                Button(action:{
                                    
                                }){
                                    HStack {
                                        Text("Edit Preferences")
                                        Image(systemName: "gear")
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }.listStyle(SidebarListStyle())
        .onAppear() {
            store.dispatch(LibraryThunkCreatorImpl().loadLibraryState())
        }.onDrop(of: ["public.url","public.file-url"], isTargeted: nil) { (items) -> Bool in
            if let item = items.first {
                if let identifier = item.registeredTypeIdentifiers.first {
                    print("onDrop with identifier = \(identifier)")
                    if identifier == "public.url" || identifier == "public.file-url" {
                        item.loadItem(forTypeIdentifier: identifier, options: nil) { (urlData, error) in
                            DispatchQueue.main.async {
                                if let urlData = urlData as? Data {
                                    let url = NSURL(absoluteURLWithDataRepresentation: urlData, relativeTo: nil) as URL
                                    let thunk = LibraryThunkCreatorImpl().createAddNodeThunk(url: url)
                                    store.dispatch(thunk)
                                }
                            }
                        }
                    }
                }
                return true
            } else {
                print("item not here")
                return false
            }
        }
    }
}

struct LibraryNodeChildView: View {
    let node: LibraryNode
    var body: some View {
        HStack {
            if let image = node.image {
                Image(nsImage: image)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 15, height: 15)
            }
            Text(verbatim: node.displayName).onDrag {
                NSItemProvider(object: node.url as NSURL)                
            }.allowsHitTesting(false)
            .font(.subheadline)
        }
    }
}

标签: iosswiftlistswiftui

解决方案


正如这里提到的,解决方案是将拖放绑定到项目容器,并将上下文菜单绑定到容器内的项目。

HStack {
   Text(verbatim: node.displayName)
       .contextMenu {
           // handle context menu
       }
   }
   .onDrag {
       // handle drag
   }
}

推荐阅读