1

I write the following code for date picker customization, and get the output as Output image

Here I want to add the forward and Backword buttons for the Date picker this way Expect output

Anyone help me with my code modification to add forward and Backword buttons with Expect output]2

Give any idea or share any references with me.

    struct CalendarDay: Identifiable {
    let id = UUID()
    var number: String
    var weekday: String
    var isToday: Bool
}

struct ContentView: View {
    @State var days = [CalendarDay]()
    
    var body: some View {
        ZStack{
            VStack {
                
                Button(action:{
                    //Button Action
                    })
                    .padding(.leading, 10)
                Spacer()
                ScrollView(.horizontal, showsIndicators: false){
                    HStack(spacing: 20) {
                  ForEach(days.indices, id: \.self) { i in
                        CalendarView(
                            number: self.days[i].number,
                            days: self.days[i].weekday,
                            color: self.days[i].isToday ? #colorLiteral(red: 0.9060331583, green: 0.2547450066, blue: 0.3359550834, alpha: 1) : #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
                            textcolor: self.days[i].isToday ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) : #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
                        )
                            .onTapGesture{
                                print(self.days[i])
                                // this is just for replacing the current selection
                                for j in self.days.indices { self.days[j].isToday = false }
                                self.days[i].isToday = true
                            }
                    }}
                    .padding(.leading,10)
                    .padding(.bottom, 10)
                    .shadow(radius: 3, x: 3, y: 3)
                }
                Spacer()
                Button(action:{
                                   //Button Action
                                   })
                                   .padding(.leading)
                               Spacer()
                
            }
        }
        .onAppear {
            self.getCurrentWeekdays()
        }
    }
    
    func getCurrentWeekdays() {
        /// from https://stackoverflow.com/a/62355272/14351818
        let dateComponents = Calendar(identifier: .gregorian).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())
        let startOfWeek = Calendar(identifier: .gregorian).date(from: dateComponents)!
        let startOfWeekNoon = Calendar(identifier: .gregorian).date(bySettingHour: 12, minute: 0, second: 0, of: startOfWeek)!
        
        days = (0...6).map {
            let calendar = Calendar(identifier: .gregorian)
            let date = calendar.date(byAdding: .day, value: $0, to: startOfWeekNoon)!
            
            let numberDateFormatter = DateFormatter()
            numberDateFormatter.dateFormat = "d"
            let number = numberDateFormatter.string(from: date)
            
            let weekdayDateFormatter = DateFormatter()
            weekdayDateFormatter.dateFormat = "E"
            let weekday = weekdayDateFormatter.string(from: date)
            
            let calendarDay = CalendarDay(
                number: number,
                weekday: weekday,
                isToday: calendar.component(.day, from: Date()) == calendar.component(.day, from: date)
            )
            
            return calendarDay
        }
        
    }
}

struct CalendarView: View {
    var number : String
    var days : String
    var color : UIColor
    var textcolor : UIColor
    
    var body: some View {
        VStack{
            Text(self.number)
                .font(.system(size: 20, weight: .bold, design: .rounded))
                .foregroundColor(Color(self.textcolor))
            Text(self.days)
                .font(.headline)
                .foregroundColor(Color(self.textcolor))
        }.padding([.top,.bottom], 10)
            .padding([.leading,.trailing],10)
            .background(Color(self.color))
            .cornerRadius(30)
    }
}

2 Answers2

1

you could try something like this: edited for ScrollViewReader

struct ContentView: View {

@State var days = [CalendarDay]()
@State var selectedDay: Int = 0

var body: some View {
    ScrollViewReader { scrollProxy in
        HStack {
            Button(action: {
                if selectedDay > 0 {
                    for j in days.indices { days[j].isToday = false }
                    days[selectedDay-1].isToday = true
                    selectedDay -= 1
                    withAnimation { scrollProxy.scrollTo(selectedDay) }
                }
            }) {
                Image(systemName: "chevron.left.circle.fill")
            }
            ZStack{
                VStack {
                    ScrollView(.horizontal, showsIndicators: false){
                        HStack(spacing: 20) {
                            ForEach(days.indices, id: \.self) { i in
                                CalendarView(
                                    number: days[i].number,
                                    days: days[i].weekday,
                                    color: days[i].isToday ? #colorLiteral(red: 0.9060331583, green: 0.2547450066, blue: 0.3359550834, alpha: 1) : #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
                                    textcolor: days[i].isToday ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) : #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
                                ).onTapGesture {
                                    selectedDay = i
                                    for j in days.indices {
                                        if j == i {
                                            days[i].isToday = true
                                        } else {
                                            days[j].isToday = false
                                        }
                                    }
                                }
                            }
                            
                        }
                        .padding(.leading,10)
                        .padding(.bottom, 10)
                        .shadow(radius: 3, x: 3, y: 3)
                    }
                }
            }
            Button(action: {
                if selectedDay < days.count-1 {
                    for j in days.indices { days[j].isToday = false }
                    days[selectedDay+1].isToday = true
                    selectedDay += 1
                    withAnimation { scrollProxy.scrollTo(selectedDay) }
                }
            }) {
                Image(systemName: "chevron.right.circle.fill")
            }
        }
    }
    .onAppear {
        getCurrentWeekdays()
    }
}
    
    func getCurrentWeekdays() {
        /// from https://stackoverflow.com/a/62355272/14351818
        let dateComponents = Calendar(identifier: .gregorian).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())
        let startOfWeek = Calendar(identifier: .gregorian).date(from: dateComponents)!
        let startOfWeekNoon = Calendar(identifier: .gregorian).date(bySettingHour: 12, minute: 0, second: 0, of: startOfWeek)!
        
        days = (0...6).map {
            let calendar = Calendar(identifier: .gregorian)
            let date = calendar.date(byAdding: .day, value: $0, to: startOfWeekNoon)!
            
            let numberDateFormatter = DateFormatter()
            numberDateFormatter.dateFormat = "d"
            let number = numberDateFormatter.string(from: date)
            
            let weekdayDateFormatter = DateFormatter()
            weekdayDateFormatter.dateFormat = "E"
            let weekday = weekdayDateFormatter.string(from: date)
            
            let calendarDay = CalendarDay(
                number: number,
                weekday: weekday,
                isToday: calendar.component(.day, from: Date()) == calendar.component(.day, from: date)
            )
            //  <--- here --->
            if calendar.component(.day, from: Date()) == calendar.component(.day, from: date) {
                selectedDay = $0
            }
            
            return calendarDay
        }
        
    }
}
1

You could also try like below-:

You can replace Text view with Image view for buttons. The Back and forward buttons retain their positions, while the date selector is still scrollable.

import SwiftUI

struct CalendarDay: Identifiable {
    let id = UUID()
    var number: String
    var weekday: String
    var isToday: Bool
}

struct Test1: View {
    @State var days = [CalendarDay]()
    
    var body: some View {
        
        HStack(){
            Button {
                
            } label: {
                
                ZStack {
                    
                    Circle()
                        .fill(Color.red)
                        .opacity(0.6)
                    
                    Circle()
                        .strokeBorder(Color.red, lineWidth: 1)
                    
                    Text("B").foregroundColor(.white)
                    
                }.frame(width: 30, height: 30)
            }.padding([.leading],3)
            
            HStack(alignment:.center){
                GeometryReader{ proxy in
                    ScrollView(.horizontal) {
                        
                        LazyHStack {
                            ForEach(days.indices, id: \.self) { i in
                                CalendarView(
                                    number: days[i].number,
                                    days: days[i].weekday,
                                    color: days[i].isToday ? #colorLiteral(red: 0.9060331583, green: 0.2547450066, blue: 0.3359550834, alpha: 1) : #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1),
                                    textcolor: days[i].isToday ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) : #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1), proxy: proxy
                                )
                                .onTapGesture{
                                    print(days[i])
                                    // this is just for replacing the current selection
                                    for j in days.indices { days[j].isToday = false }
                                    days[i].isToday = true
                                }
                            }
                        }
                    }
                }
            }
            .padding([.trailing,.leading],3)
            
            
            Button {
                
            } label: {
                ZStack {
                    Circle()
                        .fill(Color.red)
                        .opacity(0.6)
                    
                    Circle()
                        .strokeBorder(Color.red, lineWidth: 1)
                    
                    Text("F").foregroundColor(.white)
                }.frame(width: 30, height: 30)
            }.padding([.trailing],3)
        }
        
        .shadow(radius: 3, x: 3, y: 3)
        .onAppear {
            getCurrentWeekdays()
        }
    }
    
    func getCurrentWeekdays() {
        /// from https://stackoverflow.com/a/62355272/14351818
        let dateComponents = Calendar(identifier: .gregorian).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())
        let startOfWeek = Calendar(identifier: .gregorian).date(from: dateComponents)!
        let startOfWeekNoon = Calendar(identifier: .gregorian).date(bySettingHour: 12, minute: 0, second: 0, of: startOfWeek)!
        
        days = (0...20).map {
            let calendar = Calendar(identifier: .gregorian)
            let date = calendar.date(byAdding: .day, value: $0, to: startOfWeekNoon)!
            
            let numberDateFormatter = DateFormatter()
            numberDateFormatter.dateFormat = "d"
            let number = numberDateFormatter.string(from: date)
            
            let weekdayDateFormatter = DateFormatter()
            weekdayDateFormatter.dateFormat = "E"
            let weekday = weekdayDateFormatter.string(from: date)
            
            let calendarDay = CalendarDay(
                number: number,
                weekday: weekday,
                isToday: calendar.component(.day, from: Date()) == calendar.component(.day, from: date)
            )
            
            return calendarDay
        }
        
    }
}
struct CalendarView: View {
    var number : String
    var days : String
    var color : UIColor
    var textcolor : UIColor
    var proxy: GeometryProxy
    
    var body: some View {
        VStack{
            Text(self.number)
                .font(.system(size: 20, weight: .bold, design: .rounded))
                .foregroundColor(Color(self.textcolor))
            Text(self.days)
                .font(.headline)
                .foregroundColor(Color(self.textcolor))
        }
        
        .frame(width: proxy.size.width * 0.18, height:  proxy.size.width * 0.2)
        .background(Color(self.color))
        .cornerRadius(30)
    }
}

enter image description here

Tushar Sharma
  • 2,839
  • 1
  • 16
  • 38