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

iOS14.7中SwiftUI动态高度Sheet实现及日期选择器居中问题

iOS14.7 SwiftUI 动态高度Sheet日期时间选择器居中解决方案

核心修改点

  • 移除Sheet调用中的固定高度frame(height:580),让Sheet高度由内部内容自适应
  • 给图形化日期选择器设置frame(maxWidth: .infinity),确保它在容器内居中显示
  • 实现自定义导航栏与底部操作按钮的布局,适配动态高度需求

完整代码实现

Sheet调用修改

.sheet(isPresented: $showEditDataTime) {
    EditDateAndTimeView()
        .clearModalBackground()
}

EditDateAndTimeView 实现

struct EditDateAndTimeView: View {
    @Environment(\.dismiss) private var dismiss
    @State private var selectedDate = Date()
    
    var body: some View {
        VStack(spacing: 0) {
            // 自定义导航栏
            HStack {
                Button("取消") {
                    dismiss()
                }
                .foregroundColor(.blue)
                
                Spacer()
                
                Text("选择日期时间")
                    .font(.headline)
                
                Spacer()
                
                Button("确定") {
                    dismiss()
                    // 这里添加选中日期的处理逻辑
                }
                .foregroundColor(.blue)
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
            .border(.separator, edge: .bottom)
            
            // 居中的图形化日期时间选择器
            DatePicker("", selection: $selectedDate, displayedComponents: [.date, .hourAndMinute])
                .datePickerStyle(.graphical)
                .padding()
                .frame(maxWidth: .infinity)
                .background(Color(.systemBackground))
            
            Spacer()
            
            // 底部操作按钮组
            HStack(spacing: 16) {
                Button("重置") {
                    selectedDate = Date()
                }
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color(.systemGray5))
                .cornerRadius(8)
                
                Button("应用") {
                    dismiss()
                    // 这里添加应用日期的处理逻辑
                }
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(8)
            }
            .padding(.horizontal, 16)
            .padding(.bottom, 20)
        }
        .background(Color(.systemGroupedBackground))
    }
}

辅助扩展(兼容iOS14.7)

// 清除Sheet背景透明的扩展
extension View {
    func clearModalBackground() -> some View {
        if #available(iOS 15.0, *) {
            return self.presentationBackground(.clear)
        } else {
            return self
                .background(Color.clear)
                .onAppear {
                    guard let window = UIApplication.shared.windows.first else { return }
                    window.rootViewController?.presentedViewController?.view.backgroundColor = .clear
                }
        }
    }
}

// 给视图添加单边边框的扩展
extension View {
    func border(_ color: Color, edge: Edge, lineWidth: CGFloat = 1) -> some View {
        overlay(EdgeBorder(color: color, edge: edge, lineWidth: lineWidth))
    }
}

struct EdgeBorder: Shape {
    var color: Color
    var edge: Edge
    var lineWidth: CGFloat
    
    func path(in rect: CGRect) -> Path {
        var path = Path()
        switch edge {
        case .top:
            path.move(to: CGPoint(x: rect.minX, y: rect.minY))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        case .bottom:
            path.move(to: CGPoint(x: rect.minX, y: rect.maxY))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        case .leading:
            path.move(to: CGPoint(x: rect.minX, y: rect.minY))
            path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        case .trailing:
            path.move(to: CGPoint(x: rect.maxX, y: rect.minY))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        }
        return path.strokedPath(.init(lineWidth: lineWidth))
    }
}

关键说明

  1. 日期选择器居中:通过frame(maxWidth: .infinity)让选择器占满父容器的可用宽度,配合padding()保证左右边距,实现居中效果。
  2. 动态高度Sheet:移除固定高度后,Sheet会根据内部VStack的内容自动计算高度,Spacer会将底部按钮推至Sheet底部。
  3. iOS14.7兼容:针对iOS14的Sheet背景透明处理使用了UIKit的API,自定义导航栏的单边边框通过Shape实现,避免使用iOS15+的专属API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:35:38