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

SwiftUI列表内部无法滚动求助:保留手势与onDelete的解决方案

SwiftUI List滚动异常修复:保留手势同时恢复滚动功能

问题根源

你遇到的滚动失效问题,是因为onTapGesture这类默认手势修饰符会独占触摸事件——当触摸列表元素时,点击手势会优先被识别,直接阻断了List原生的滚动手势响应。

解决方案

将所有自定义手势(包括点击、长按)都通过simultaneousGesture添加,该修饰符允许多个手势同时被识别,既保留自定义手势功能,又不影响List的滚动。

修改后的代码

List {
    ForEach(fetchRequest, id: \.self) { task in
        Text(task.desc!)
            .foregroundColor(task.done ? .white : task.today ? .white : .black)
            .listRowBackground(task.done ? Color.green : task.today ? Color.blue : Color.white)
            // 将onTapGesture替换为simultaneousGesture包裹的TapGesture
            .simultaneousGesture(TapGesture().onEnded {
                self.taskToEdit = task
            })
            .swipeActions(allowsFullSwipe: true) {
                Button(role: .cancel) {
                    task.done.toggle()
                    task.today = false
                    task.date_completion = Date()
                    
                    do {try viewContext.save()} catch {
                        let nsError = error as NSError
                        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                    }
                    
                    print("mark as done")
                } label: {
                    Label("Done", systemImage: "checkmark")
                }
                .tint(.green)
            }
            .simultaneousGesture(LongPressGesture()
                .onEnded { _ in
                    let impactMed = UIImpactFeedbackGenerator(style: .light)
                    impactMed.impactOccurred()
                    
                    task.today.toggle()
                    
                    do {try viewContext.save()} catch {
                        let nsError = error as NSError
                        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                    }
                    
                    print("Loooong")
                    print(task.today)
                }
            )
    }
    .onDelete(perform: deleteItems)
}
//.listRowSeparator(.hidden)
//.listRowInsets(.init(top: 4, leading: 8, bottom: 4, trailing: 8))
.sheet(item: self.$taskToEdit, content: { taskToEdit in
    itemDetail(taskItem: taskToEdit, textFieldText: taskToEdit.detail ?? "")
})

补充说明

  • simultaneousGesture不会改变手势的触发逻辑,只是允许它和其他手势(比如List的滚动)同时被系统识别
  • 如果你需要让某个手势优先于滚动,可以使用highPriorityGesture,但这种情况会再次阻断滚动,仅在特殊场景使用

内容的提问来源于stack exchange,提问作者Nat Serrano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:15:45