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

SwiftUI同一视图中为两个按钮实现日期/时间选择器弹窗

解决SwiftUI中两个按钮分别弹出日期/时间选择器的问题

你的代码目前只给日期按钮绑定了弹窗逻辑,时间按钮缺少对应的popover配置。只需要添加时间选择器的弹窗绑定,并复用已有的DatePopover组件即可实现需求,同时可以优化交互体验:

关键修改点

  1. 为showTimePicker添加对应的popover,传入时间选择器的组件参数
  2. 优化按钮显示,增加已选中的日期/时间文本,提升用户感知
  3. 调整弹窗关闭逻辑,添加确认按钮避免选择过程中意外关闭弹窗

修改后的完整代码

struct SwiftUIView: View {
    @State private var showDatePicker = false
    @State private var deliveryDate = Date()
    @State private var showTimePicker = false
    @State private var deliveryTime = Date()

    var body : some View{
        VStack(spacing:15){
            // 配送日期按钮
            Button {
                showDatePicker = true
            } label: {
                HStack{
                    Text("Delivery Date")
                    Spacer()
                    // 显示已选中的日期
                    Text(deliveryDate.formatted(date: .long, time: .omitted))
                        .foregroundColor(.black)
                    Image(systemName: "calendar")
                }
                .foregroundColor(Color.gray)
                .frame(maxWidth: .infinity)
            }.padding()
            .background {
                RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 2)
            }

            // 配送时间按钮
            Button {
                showTimePicker = true
            } label: {
                HStack{
                    Text("Delivery Time")
                    Spacer()
                    // 显示已选中的时间
                    Text(deliveryTime.formatted(date: .omitted, time: .shortened))
                        .foregroundColor(.black)
                    Image(systemName: "clock")
                }
                .foregroundColor(Color.gray)
                .frame(maxWidth: .infinity)
            }.padding()
            .background {
                RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 2)
            }
        }
        .padding()
        // 日期选择器弹窗
        .popover(isPresented: $showDatePicker) {
            DatePopover(components: [.date], dateIn: $deliveryDate, isShowing: $showDatePicker)
        }
        // 时间选择器弹窗(新增)
        .popover(isPresented: $showTimePicker) {
            DatePopover(components: [.hourAndMinute], dateIn: $deliveryTime, isShowing: $showTimePicker)
        }
    }
}

// 可复用的日期/时间选择器弹窗
struct DatePopover: View {
    var components : DatePickerComponents
    @Binding var dateIn: Date
    @Binding var isShowing: Bool

    var body: some View {
        VStack(spacing: 20) {
            DatePicker("", selection: $dateIn, in: Date.now..., displayedComponents: components)
                .datePickerStyle(.graphical)
                .padding(.all, 20)
            
            // 添加确认按钮,让用户主动关闭弹窗
            Button("Done") {
                isShowing = false
            }
            .font(.headline)
            .padding(.horizontal, 40)
            .padding(.vertical, 10)
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
        .frame(width: 400, height: 450, alignment: .center)
        .padding()
    }
}

说明

  • 时间选择器通过传入components: [.hourAndMinute]参数,让DatePicker只显示时间选择界面
  • 按钮中新增的格式化文本,能让用户直观看到当前选中的日期/时间
  • 弹窗中添加的Done按钮,避免了原代码中选择时自动关闭弹窗的突兀体验,交互更流畅

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:37:50