SwiftUI中能否让onDrag函数触发时机改为触摸按下而非长按?
SwiftUI 修改onDrag触发时机为触摸按下
可以实现将onDrag的触发逻辑从默认的长按改为触摸按下。系统默认的onDrag绑定了长按手势,要修改触发时机,需要通过自定义手势组合替代默认逻辑,直接在触摸按下时启动拖拽流程。
核心实现思路
使用DragGesture并将其minimumDistance设为0(确保触摸按下瞬间触发),结合GestureState跟踪拖拽状态,手动模拟系统onDrag的拖拽数据传递逻辑,同时配合onDrop完成项目重新排序(对应你提到的LazyGrid场景)。
完整示例代码
import SwiftUI struct ReorderableGrid: View { @State private var items = (1...20).map { "Item \($0)" } @GestureState private var currentDraggingItem: String? = nil private let gridColumns = [GridItem(.flexible()), GridItem(.flexible())] var body: some View { ScrollView { LazyVGrid(columns: gridColumns, spacing: 16) { ForEach(items, id: \.self) { item in Text(item) .padding() .background(currentDraggingItem == item ? .gray.opacity(0.6) : .blue) .foregroundColor(.white) .cornerRadius(8) // 自定义触摸按下触发的拖拽手势 .gesture( DragGesture(minimumDistance: 0) .updating($currentDraggingItem) { _, state, _ in state = item } .onChanged { _ in // 手动创建拖拽数据提供者,模拟onDrag的核心逻辑 let itemProvider = NSItemProvider(object: item as NSString) } ) // 处理放置逻辑 .onDrop(of: [.text], delegate: GridDropDelegate(targetItem: item, items: $items, draggingItem: $currentDraggingItem)) } } .padding() } } } // 自定义DropDelegate处理拖拽放置后的排序 struct GridDropDelegate: DropDelegate { let targetItem: String @Binding var items: [String] @Binding var draggingItem: String? func performDrop(info: DropInfo) -> Bool { guard let draggedItem = draggingItem, draggedItem != targetItem else { return false } guard let sourceIndex = items.firstIndex(of: draggedItem), let targetIndex = items.firstIndex(of: targetItem) else { return false } withAnimation { items.move(fromOffsets: IndexSet(integer: sourceIndex), toOffset: targetIndex > sourceIndex ? targetIndex + 1 : targetIndex) } draggingItem = nil return true } func dropEntered(info: DropInfo) { // 可选:添加拖拽进入时的视觉反馈,比如缩放目标视图 } } struct ReorderableGrid_Previews: PreviewProvider { static var previews: some View { ReorderableGrid() } }
关键细节说明
DragGesture(minimumDistance: 0):将手势的最小触发距离设为0,确保触摸按下的瞬间就触发拖拽逻辑,替代默认的长按等待。GestureState:实时跟踪当前拖拽的项目,用于提供即时视觉反馈(比如拖拽时改变视图背景色)。NSItemProvider:系统onDrag内部会自动创建该对象传递拖拽数据,自定义手势时需要手动生成,保证onDrop能识别拖拽的内容。DropDelegate:负责处理拖拽放置后的位置更新,实现LazyGrid内的项目重新排序逻辑。
内容的提问来源于stack exchange,提问作者appsofgoodlife
相关产品推荐
相关产品推荐

