swiftswiftuiswiftui-tabviewswiftui-datepicker

How could I implement TabView page switching as a function of a selected date from DatePicker?


I've implemented the following code for my TabView and a DatePicker. I can currently slide between the three pages. And I can use the DatePicker to select between the 3 permitted days

import SwiftUI

struct DailyOverviewTab: View {
   @State private var date = Date()

   let dateRange: ClosedRange<Date> = {
      let calendar = Calendar.current
      let startComponents = DateComponents(year: 2024, month: 5, day: 6)
      let endComponents = DateComponents(year: 2024, month, 5, day: 8)
      return calendar.date(from: startComponents)! ... calendar.date(from: endComponents)
   }()

   var body: some View {
      TabView() {
         Six_May()
            .tag(1)
         Seven_May()
            .tag(2)
         Eight_May()
            .tag(3)
      }
      .tabViewStyle(.page)
      .foregroundColor(.green)
      
      DatePicker("", selection: $date, in: dateRange, displayedComponents: [.date])
         .datePickerStyle(.compact)
         .labelsHidden()
   }
}

However, I don't know how to use the selected date in order to switch pages. I would like to be able to switch pages both by swiping and by using the date in the DatePicker to go to a specific page. I only have 3 pages now, but I anticipate having much more, so using a calendar to go to a specific page would be ideal.

I tried using date.formatted(date: .complete, time: .omitted) to assign the selected date to a variable. I don't know how to use this variable to change the TabView though.


Solution

  • You could try this approach, using the $date in both the TabView selection, and the DatePicker ...to be able to switch pages both by swiping and by using the date in the DatePicker to go to a specific page. Note the .tag() in the TabView. You will have to adjust the logic when dates not in the range are selected, and take into account local timezone if required.

    struct ContentView: View {
        var body: some View {
            DailyOverviewTab()
        }
    }
    
    struct DailyOverviewTab: View {
        @State private var date = Date()
    
        let dateRange: ClosedRange<Date> = {
            let calendar = Calendar.current
            let startComponents = DateComponents(year: 2024, month: 5, day: 6)
            let endComponents = DateComponents(year: 2024, month: 5, day: 8)
            return calendar.date(from: startComponents)! ... calendar.date(from: endComponents)!
        }()
        
        let sixmay = Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 6))!
        let sevenmay = Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 7))!
        let eightmay = Calendar.current.date(from: DateComponents(year: 2024, month: 5, day: 8))!
        
        var body: some View {
            TabView(selection: $date) {
                Six_May().tag(sixmay)
                Seven_May().tag(sevenmay)
                Eight_May().tag(eightmay)
            }
            .tabViewStyle(.page)
            .foregroundColor(.green)
            
            DatePicker("", selection: $date, in: dateRange, displayedComponents: [.date])
                .datePickerStyle(.compact)
                .labelsHidden()
                .onAppear {
                    date = dateRange.lowerBound
                }
        }
        
    }
    
    struct Six_May: View {
        var body: some View {
            Text("Six_May")
        }
    }
    struct Seven_May: View {
        var body: some View {
            Text("Seven_May")
        }
    }
    struct Eight_May: View {
        var body: some View {
            Text("Eight_May")
        }
    }