滚动上的 SwiftUI 日历获取当前月份

问题描述

我试图在滚动日历时获取当前月份。我的目标是使用当前月份的标题,然后当视图向下滚动到新的月份时,标题会更新相应的月份。我尝试使用 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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...