SwiftUI中实现提醒App新建提醒表单的底部弹出卡片组件是什么?
实现从底部弹出的可滑动关闭覆盖卡片
SwiftUI没有直接对应这种“底部弹出卡片”的内置组件,但可以通过两种方案快速实现你要的效果:
方案一:iOS 15+ 用系统Sheet自定义配置
从iOS15开始,系统Sheet支持自定义弹出高度和拖动指示器,自带滑动关闭逻辑,是最省心的方案:
struct ContentView: View { @State private var isSheetShown = false var body: some View { Button("打开表单") { isSheetShown = true } .sheet(isPresented: $isSheetShown) { // 这里放你的表单内容 Form { TextField("输入名称", text: .constant("")) Toggle("开启选项", isOn: .constant(false)) Button("提交") { isSheetShown = false } } .presentationDetents([.medium, .large]) // 设置可停留的高度(中等/全屏) .presentationDragIndicator(.visible) // 显示顶部拖动条 } } }
presentationDetents:控制卡片的弹出高度,.medium对应约一半屏幕高度,.large是全屏presentationDragIndicator:显示顶部的拖动指示器,用户可拖动它调整高度或直接滑走关闭
方案二:自定义底部卡片(兼容iOS 15以下)
如果需要支持更早iOS版本,可通过手势+动画封装自定义组件:
struct CustomBottomCard<Content: View>: View { @Binding var isPresented: Bool let content: Content @State private var dragOffset = CGSize.zero init(isPresented: Binding<Bool>, @ViewBuilder content: () -> Content) { self._isPresented = isPresented self.content = content() } var body: some View { ZStack(alignment: .bottom) { if isPresented { // 背景遮罩,点击可关闭 Color.black.opacity(0.3) .ignoresSafeArea() .onTapGesture { isPresented = false } // 卡片主体 VStack(spacing: 0) { // 顶部拖动条 Rectangle() .frame(width: 40, height: 6) .cornerRadius(3) .foregroundColor(.gray) .padding(.top, 10) content } .background(Color.white) .cornerRadius(16, corners: [.topLeft, .topRight]) .offset(y: dragOffset.height) .gesture( DragGesture() .onChanged { value in if value.translation.height > 0 { // 仅允许向下拖动 dragOffset = value.translation } } .onEnded { value in if value.translation.height > 100 { // 拖动距离超过阈值则关闭 isPresented = false } dragOffset = .zero } ) .transition(.move(edge: .bottom)) .animation(.spring(), value: isPresented) } } } } // 使用示例 struct ContentView: View { @State private var isCardShown = false var body: some View { Button("打开自定义卡片") { isCardShown = true } .overlay( CustomBottomCard(isPresented: $isCardShown) { Form { TextField("用户名", text: .constant("")) SecureField("密码", text: .constant("")) Button("登录") { isCardShown = false } } .frame(height: 300) } ) } }
- 自定义组件通过
ZStack在页面底部叠加卡片,背景遮罩点击可快速关闭 - 利用
DragGesture监听拖动动作,达到设定阈值时触发关闭逻辑,配合过渡动画实现弹出/关闭效果
核心说明
SwiftUI没有直接命名为“覆盖卡片”的内置组件,但上述两种方案完全可以实现你要的需求:
- iOS15及以上优先用系统Sheet的自定义配置,体验和系统原生一致,无需额外封装
- 低版本则需要自己封装组件,核心是手势监听+动画过渡的组合使用
内容的提问来源于stack exchange,提问作者Chip Bell
相关产品推荐
相关产品推荐

