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

请求开发SwiftUI通用侧滑组件:类TableView/List侧滑动作适配任意视图

极简通用SwiftUI侧滑操作组件

这里实现一个轻量、通用的侧滑组件,能给任意SwiftUI视图添加左滑显示操作按钮的功能,和UITableView的侧滑逻辑一致,同时支持在任何父视图中使用。

核心组件实现

import SwiftUI

struct SlideSwipeView<Content: View, Actions: View>: View {
    let content: Content
    let actions: Actions
    let actionWidth: CGFloat
    
    @State private var offset: CGFloat = 0
    
    init(actionWidth: CGFloat = 80, @ViewBuilder content: () -> Content, @ViewBuilder actions: () -> Actions) {
        self.actionWidth = actionWidth
        self.content = content()
        self.actions = actions()
    }
    
    var body: some View {
        HStack(spacing: 0) {
            content
            actions
                .frame(width: actionWidth)
        }
        .offset(x: -offset)
        .gesture(
            DragGesture()
                .onChanged { value in
                    let translation = value.translation.width
                    // 限制滑动范围:0到actionWidth
                    offset = max(0, min(-translation, actionWidth))
                }
                .onEnded { value in
                    // 滑动超过一半时自动展开,否则收起
                    let shouldOpen = -value.translation.width > actionWidth / 2
                    withAnimation(.spring()) {
                        offset = shouldOpen ? actionWidth : 0
                    }
                }
        )
        .onTapGesture {
            // 点击主视图收起操作栏
            withAnimation(.spring()) {
                offset = 0
            }
        }
    }
}

// 便捷构造器,支持单个操作按钮
extension SlideSwipeView where Actions == Button<Text> {
    init(actionWidth: CGFloat = 80, title: String, titleColor: Color = .white, bgColor: Color = .red, action: @escaping () -> Void, @ViewBuilder content: () -> Content) {
        self.init(actionWidth: actionWidth, content: content) {
            Button(title) {
                action()
                withAnimation(.spring()) {
                    self.offset = 0
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(bgColor)
            .foregroundColor(titleColor)
        }
    }
}

使用示例

1. 给普通文本添加侧滑删除

SlideSwipeView(title: "删除", action: {
    print("执行删除操作")
}) {
    Text("这是一条可侧滑的文本")
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .background(Color(.systemGray6))
}

2. 给自定义卡片添加多个操作按钮

SlideSwipeView(actionWidth: 160) {
    VStack(alignment: .leading, spacing: 8) {
        Text("自定义卡片")
            .font(.headline)
        Text("支持多个操作按钮,滑动范围可自定义")
            .font(.caption)
            .foregroundColor(.gray)
    }
    .padding()
    .frame(maxWidth: .infinity, alignment: .leading)
    .background(Color(.systemGray6))
} actions: {
    HStack(spacing: 0) {
        Button("标记") {
            print("标记为已读")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(.systemBlue))
        .foregroundColor(.white)
        
        Button("删除") {
            print("删除卡片")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(.systemRed))
        .foregroundColor(.white)
    }
}

3. 在List中使用(替代原生侧滑)

List(0..<10) { index in
    SlideSwipeView(title: "删除", action: {
        print("删除第\(index)行")
    }) {
        HStack {
            Text("列表项 \(index)")
            Spacer()
            Image(systemName: "chevron.right")
                .foregroundColor(.gray)
        }
        .padding()
    }
    .listRowInsets(EdgeInsets()) // 移除默认内边距,让侧滑铺满整行
}

关键设计要点

  • 通用性:通过泛型支持任意主视图和操作视图,不管是简单文本还是复杂卡片都能适配
  • 手势控制:使用DragGesture处理滑动,限制滑动范围避免过度偏移,滑动结束时根据距离自动展开/收起
  • 交互反馈:点击主视图自动收起操作栏,操作按钮点击后也自动收起,符合用户习惯
  • 可配置性:支持自定义操作栏宽度,单个按钮提供便捷构造器,多按钮可自由组合布局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:33:27