问题描述
我试图在滚动日历时获取当前月份。我的目标是使用当前月份的标题,然后当视图向下滚动到新的月份时,标题会更新相应的月份。我尝试使用 Lazyvstack 并在 onAppear 方法中设置当前月份,但使用 lazyvstack 从来都不是一致的,并且总是关闭几个月。下面的代码针对 iPad 日历月视图进行了优化。
import SwiftUI
fileprivate extension DateFormatter {
static var month: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM"
return formatter
}
static var monthAndYear: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM yyyy"
return formatter
}
}
fileprivate extension Calendar {
func generateDates(
inside interval: DateInterval,matching components: DateComponents
) -> [Date] {
var dates: [Date] = []
dates.append(interval.start)
enumerateDates(
startingAfter: interval.start,matching: components,matchingPolicy: .nextTime
) { date,_,stop in
if let date = date {
if date < interval.end {
dates.append(date)
} else {
stop = true
}
}
}
return dates
}
}
struct WeekView<DateView>: View where DateView: View {
@Environment(\.calendar) var calendar
let week: Date
let content: (Date) -> DateView
init(week: Date,@viewbuilder content: @escaping (Date) -> DateView) {
self.week = week
self.content = content
}
private var days: [Date] {
guard
let weekInterval = calendar.dateInterval(of: .weekOfYear,for: week)
else { return [] }
return calendar.generateDates(
inside: weekInterval,matching: DateComponents(hour: 0,minute: 0,second: 0)
)
}
func dateInWeekened(date: Date) -> Bool {
var bool = false
if Calendar.current.isDateInWeekend(date) {
bool = true
}
return bool
}
var body: some View {
HStack(spacing: 0.0) {
ForEach(days,id: \.self) { date in
HStack(alignment: .top,spacing: 0.0) {
Divider()
vstack(alignment: .trailing,spacing: 0.0){
if self.calendar.isDate(self.week,equalTo: date,toGranularity: .month) {
HStack{
Spacer()
self.content(date)
.foregroundColor(dateInWeekened(date: date) == true ? .secondary : .primary)
.padding(8)
}
} else {
HStack{
Spacer()
self.content(date)
.hidden()
}
}
Spacer()
}
}
.frame(height: UIScreen.screenHeight / 7)
.background(dateInWeekened(date: date) == true ? Color("CalendarWeekenedColor") : Color(.systemBackground))
.edgesIgnoringSafeArea(.all)
}
}
}
}
struct MonthView<DateView>: View where DateView: View {
@Environment(\.calendar) var calendar
let month: Date
let showHeader: Bool
let content: (Date) -> DateView
init(
month: Date,showHeader: Bool = true,@viewbuilder content: @escaping (Date) -> DateView
) {
self.month = month
self.content = content
self.showHeader = showHeader
}
private var weeks: [Date] {
guard
let monthInterval = calendar.dateInterval(of: .month,for: month)
else { return [] }
return calendar.generateDates(
inside: monthInterval,second: 0,weekday: calendar.firstWeekday)
)
}
private var header: some View {
let component = calendar.component(.month,from: month)
let formatter = component == 1 ? DateFormatter.monthAndYear : .month
return
HStack{Text(formatter.string(from: month))
.font(.title)
.padding()
Spacer()
}.padding(.leading)
}
var body: some View {
vstack(spacing: 0.0) {
if showHeader {
header
}
else {
ForEach(weeks,id: \.self) { week in
WeekView(week: week,content: self.content)
.edgesIgnoringSafeArea(.all)
Divider()
.edgesIgnoringSafeArea(.all)
}
}
}
}
}
struct CalendarView<DateView>: View where DateView: View {
@Environment(\.calendar) var calendar
let interval: DateInterval
let content: (Date) -> DateView
@Binding var curentDate: Date
@State var position = 0
init(interval: DateInterval,@viewbuilder content: @escaping (Date) -> DateView,currentDate: Binding<Date>) {
self.interval = interval
self.content = content
self._curentDate = currentDate
}
private var months: [Date] {
calendar.generateDates(
inside: interval,matching: DateComponents(day: 1,hour: 0,second: 0)
)
}
var body: some View {
ScrollView(.vertical,showsIndicators: false) {
Lazyvstack(spacing: 0.0){
ForEach(months,id: \.self) { month in
MonthView(month: month,showHeader: false,content: self.content)
.edgesIgnoringSafeArea(.all)
.frame(maxHeight: .infinity)
.onAppear {
let component = calendar.component(.month,from: month)
let formatter = component == 1 ? DateFormatter.monthAndYear : .month
print("Current Month is \(formatter.string(from: month))")
}
}
}
}
}
}
struct CalendarMonthView: View {
@Environment(\.calendar) var calendar
@Binding var currentDate: Date
private var year: DateInterval {
calendar.dateInterval(of: .year,for: Date())!
}
var body: some View {
CalendarView(interval: year,content: { date in
Text("30")
.hidden()
.overlay(
Text(String(self.calendar.component(.day,from: date)))
)
},currentDate: $currentDate)
.background(Color("NavigationBarColor"))
.edgesIgnoringSafeArea(.all)
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)