请求开发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
相关产品推荐
相关产品推荐

