You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI同列表内拖拽失效跨列表正常的原因解析

问题原因

同一List内拖放无绿色提示、跨List却正常的核心原因是SwiftUI List自带内置的行拖拽排序逻辑:当你给单个List行添加独立的onDrag和onDrop时,List的默认拖拽系统会优先接管交互,覆盖自定义的拖放逻辑,导致目标行的绿色高亮提示无法触发。而跨List拖放时,两个List属于独立的拖放容器,没有内置排序逻辑的干扰,自定义onDrop能正常响应。

解决方法

要在同一List内实现自定义拖放并显示正确的视觉提示,可按以下方式调整:

1. 手动跟踪拖放目标状态

给onDrop的isTargeted参数传入Binding<Bool>,通过状态绑定控制目标元素的高亮样式,替代List默认的视觉提示逻辑:

import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
    @State private var isT2Targeted = false
    
    var body: some View {
        VStack {
            List {
                Text("t1")
                    .onDrag {
                        NSItemProvider(object: "aaaa" as NSString)
                    }
                
                Text("t2")
                    .background(isT2Targeted ? Color.green.opacity(0.3) : Color.clear)
                    .onDrop(of: [UTType.text], isTargeted: $isT2Targeted) { providers, location in
                        // 处理拖放内容
                        providers.first?.loadObject(ofClass: NSString.self) { item, error in
                            if let text = item as? String {
                                print("拖放内容:\(text)")
                            }
                        }
                        return true
                    }
            }
            
            List {
                Text("t3")
                    .onDrag {
                        NSItemProvider(object: "aaaa" as NSString)
                    }
                
                Text("t4")
                    .onDrop(of: [UTType.text], isTargeted: nil) { providers, location in
                        return true
                    }
            }
        }
    }
}

2. 使用自定义拖放代理(更灵活的方案)

通过DropDelegate协议直接控制拖放的整个生命周期,完全绕过List的默认拖拽逻辑,适合复杂交互场景:

import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
    @State private var isT2Targeted = false
    
    var body: some View {
        VStack {
            List {
                Text("t1")
                    .onDrag {
                        NSItemProvider(object: "aaaa" as NSString)
                    }
                
                Text("t2")
                    .background(isT2Targeted ? Color.green.opacity(0.3) : Color.clear)
                    .onDrop(of: [UTType.text], delegate: CustomDropDelegate(isTargeted: $isT2Targeted))
            }
            
            List {
                Text("t3")
                    .onDrag {
                        NSItemProvider(object: "aaaa" as NSString)
                    }
                
                Text("t4")
                    .onDrop(of: [UTType.text], isTargeted: nil) { providers, location in
                        return true
                    }
            }
        }
    }
}

class CustomDropDelegate: DropDelegate {
    @Binding var isTargeted: Bool
    
    init(isTargeted: Binding<Bool>) {
        _isTargeted = isTargeted
    }
    
    func dropEntered(info: DropInfo) {
        isTargeted = true
    }
    
    func dropExited(info: DropInfo) {
        isTargeted = false
    }
    
    func performDrop(info: DropInfo) -> Bool {
        isTargeted = false
        // 处理拖放内容逻辑
        return true
    }
}

内容的提问来源于stack exchange,提问作者János

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:57:16