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

SwiftUI开发待办应用:不使用List实现基于索引的滑动删除

不使用List实现ScrollView中任务项的滑动删除

方法一:利用SwiftUI内置的.swipeActions修饰符

SwiftUI的.swipeActions并非List专属,你可以给每个任务项的容器View添加该修饰符来实现滑动删除功能。只需把你的TextField包裹在一个容器(比如HStack)中,然后给容器添加滑动操作即可:

import SwiftUI

struct TodoView: View {
    @State private var tasks = ["Buy groceries", "Finish report", "Call mom"]
    private let textColor: Color = .black
    private let backgroundColor: Color = .gray.opacity(0.2)
    
    var body: some View {
        ScrollView {
            ForEach(tasks.indices, id: \.self) { index in
                // 用HStack包裹TextField作为滑动操作的载体
                HStack {
                    TextField("Activity here", text: $tasks[index])
                        .cornerRadius(20)
                        .foregroundColor(textColor)
                        .background(backgroundColor)
                        .padding(.leading, 10)
                        .padding(.trailing, 10)
                        .padding(.top, 5)
                }
                .swipeActions(edge: .trailing) {
                    Button(role: .destructive) {
                        // 执行删除操作
                        tasks.remove(at: index)
                    } label: {
                        Label("Delete", systemImage: "trash")
                    }
                }
            }
        }
        .frame(height: 600, alignment: .topLeading)
    }
}

关键说明:

  • .swipeActions必须附加到每个独立的任务项容器上,而不是ScrollView或TextField本身
  • 使用role: .destructive会让按钮自动显示为红色,符合iOS的删除操作视觉规范
  • 直接通过tasks.remove(at: index)修改数据源,UI会自动更新

方法二:自定义拖拽手势实现滑动删除

如果你需要更个性化的滑动交互效果,可以用DragGesture手动实现:

import SwiftUI

struct TodoView: View {
    @State private var tasks = ["Buy groceries", "Finish report", "Call mom"]
    @State private var deletingIndex: Int? = nil
    private let textColor: Color = .black
    private let backgroundColor: Color = .gray.opacity(0.2)
    
    var body: some View {
        ScrollView {
            ForEach(tasks.indices, id: \.self) { index in
                TextField("Activity here", text: $tasks[index])
                    .cornerRadius(20)
                    .foregroundColor(textColor)
                    .background(backgroundColor)
                    .padding(.leading, 10)
                    .padding(.trailing, 10)
                    .padding(.top, 5)
                    // 根据删除状态添加偏移动画
                    .offset(x: deletingIndex == index ? -150 : 0)
                    .animation(.easeInOut(duration: 0.3), value: deletingIndex)
                    .gesture(
                        DragGesture()
                            .onChanged { gesture in
                                // 向左滑动超过阈值时标记待删除项
                                if gesture.translation.width < -80 {
                                    deletingIndex = index
                                }
                            }
                            .onEnded { gesture in
                                // 滑动距离足够时执行删除
                                if gesture.translation.width < -150 {
                                    tasks.remove(at: index)
                                }
                                // 重置状态
                                deletingIndex = nil
                            }
                    )
            }
        }
        .frame(height: 600, alignment: .topLeading)
    }
}

关键说明:

  • 通过offset和animation实现滑动时的位移效果
  • 可以自定义滑动阈值(比如示例中的80和150)来调整触发删除的灵敏度
  • 这种方法适合需要自定义动画或交互逻辑的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:15:31