I'm exploring my way through swift & swiftui trying to teach myself. My current challenge is to produce a horizontal calendar that scrolls on a single line with a week dynamically adding days as necessary. Something like the image, any pointers on where to start with something like this? I figured a single view element for each day and some kind of loop through calender dates to build up the calender ...
I'm pretty much a beginner when it comes to dates / calendars. I managed the basics of formatting / converting and adding / subtracting days & months but that's pretty much where I'm at
I've rigged this for the current month HStack of days inside a scrollView but I can't figure out how to go about identifying which subview is visible in the centre of the scrollView - in part to be able to update the month name.
struct SingleCalendarView: View {
@State var monthString: String = "Not Set"
let calendar = Calendar.current
//var day:[Date]
var body: some View {
let dates = getWeek()
VStack {
Text(getMonth(date: Date()))
ScrollView(.horizontal) {
HStack {
ForEach(dates, id: \.self) { day in
VStack {
Text(getDayShort(date: day))
.font(.title3)
Text("\(getDayNumber(date: day))")
.font(.largeTitle)
}
.frame(width: 100, height: 100)
}
}
}
}
}
func getMonth(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "LLLL"
return dateFormatter.string(from: date)
}
func getDayShort(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "E"
return dateFormatter.string(from: date)
}
func getDayNumber(date: Date) -> Int {
let calendar = Calendar.current
let components = calendar.dateComponents([.day], from: date)
return components.day ?? 0
}
func getWeek() -> [Date] {
let currentDate = Date()
let calendar = Calendar.current
let dayOfWeek = calendar.component(.weekday, from: currentDate)
let range = calendar.range(of: .day, in: .month, for: currentDate)!
let daysMonth = (range.lowerBound ..< range.upperBound)
.compactMap { calendar.date(byAdding: .day, value: $0 - dayOfWeek, to: currentDate) }
return daysMonth
}
}