Я попробовал свою версию приложения-календаря. Я могу изменить год, отображаемый в обзоре, с помощью кнопок со стрелками. Текущая дата окрашена в красный цвет.
Однако, если я изменю год, а затем вернусь к текущей дате, выделение исчезнет. Я не могу понять, как это изменить. Вы можете помочь мне? Здесь я покажу вам код:
import SwiftUI
struct MonthOverviewView: View {
@State private var year: Int = Calendar.current.component(.year, from: Date()) // Aktuelles Jahr
@State private var scrollProxy: ScrollViewProxy? = nil
@State private var hasScrolledToToday = false // Verhindert mehrfaches Scrollen beim Laden der View
private let calendar = Calendar.current
private let daysOfWeek = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
private let currentDay = Calendar.current.component(.day, from: Date())
private let currentMonth = Calendar.current.component(.month, from: Date())
private let currentYear = Calendar.current.component(.year, from: Date())
var body: some View {
VStack {
// Jahresnavigation mit Heute Button
HStack {
Button(action: {
year -= 1
}) {
Image(systemName: "chevron.left")
.font(.title2)
.padding()
}
// Vermeide Tausendertrennung in der Jahreszahl
Text("\(String(year))")
.font(.largeTitle)
.bold()
Button(action: {
year += 1
}) {
Image(systemName: "chevron.right")
.font(.title2)
.padding()
}
Spacer()
// Heute-Button für das Springen zum aktuellen Tag
TodayButton {
withAnimation {
scrollProxy?.scrollTo("day-\(currentDay)-\(currentMonth)", anchor: .center)
}
year = currentYear
}
}
.padding(.vertical, 10)
// Scrollbare Monatsübersicht für das gesamte Jahr
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 40) {
ForEach(1...12, id: \.self) { month in
VStack {
// Monatsüberschrift
Text("\(calendar.monthSymbols[month - 1])")
.font(.title)
.bold()
// Wochentage
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 10) {
ForEach(daysOfWeek, id: \.self) { day in
Text(day)
.font(.headline)
.frame(maxWidth: .infinity)
}
}
// Tage des Monats anzeigen
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 20) {
ForEach(getDaysInMonth(month: month, year: year), id: \.self) { day in
if day != 0 {
VStack(alignment: .leading) {
// Highlight für den aktuellen Tag durch rote Ziffer
Text("\(day)")
.font(.body) // Kleinere Ziffern
.bold()
.foregroundColor(isToday(day: day, month: month, year: year) ? .red : .black)
.padding(.bottom, 10) // Abstand zum unteren Bereich
.padding(.leading, 5)
// Platzhalter für spätere Termine, größerer Bereich
Rectangle()
.fill(Color.clear) // Hintergrundfarbe entfernen
.frame(height: 60) // Mehr Platz für Termine
}
.frame(minHeight: 120) // Vergrößerter Bereich für jeden Tag
.border(Color.gray.opacity(0.2), width: 1) // Dezenter Rahmen
.id("day-\(day)-\(month)") // Eindeutige ID für jeden Tag, damit genau dorthin gescrollt werden kann
} else {
Color.clear // Platzhalter für leere Felder
}
}
}
.padding(.horizontal)
}
}
}
.onAppear {
scrollProxy = proxy // ScrollViewProxy speichern
// Nur einmalig beim ersten Laden der Ansicht zum aktuellen Tag scrollen
if !hasScrolledToToday && year == currentYear {
DispatchQueue.main.async {
withAnimation {
proxy.scrollTo("day-\(currentDay)-\(currentMonth)", anchor: .center)
hasScrolledToToday = true // Verhindert erneutes Scrollen beim erneuten Aufrufen der View
}
}
}
}
}
}
}
}
// Funktion zur Berechnung der Tage des Monats
func getDaysInMonth(month: Int, year: Int) -> [Int] {
let dateComponents = DateComponents(year: year, month: month)
guard let firstOfMonth = calendar.date(from: dateComponents),
let range = calendar.range(of: .day, in: .month, for: firstOfMonth) else {
return []
}
let numberOfDays = range.count
let firstWeekday = calendar.component(.weekday, from: firstOfMonth) - 1 // Sonntag = 1, daher -1
var days = Array(repeating: 0, count: firstWeekday == 0 ? 6 : firstWeekday - 1) // Leerzeichen für die ersten Tage der Woche
days += Array(1...numberOfDays)
return days
}
// Überprüft, ob der aktuelle Tag angezeigt wird
func isToday(day: Int, month: Int, year: Int) -> Bool {
return day == currentDay && month == currentMonth && year == currentYear
}
}
struct TodayButton: View {
var action: () -> Void
var body: some View {
Button(action: action) {
Text("button_today")
// .font(.headline)
.padding(.horizontal)
.padding(.vertical, 8)
//.background(Color.blue.opacity(0.1))
.cornerRadius(10)
}
.padding(.trailing, 10)
}
}
Что бы я ни пытался, когда я переключаюсь обратно с другого года на текущий год, функция isToday, похоже, не выполняется, и текущая дата больше не выделяется. Кажется, это всегда происходит, когда я меняю год, потому что, пока я прокручиваю только вверх или вниз в текущем году, выделение остается при первой загрузке страницы.
Я попробовал свою версию приложения-календаря. Я могу изменить год, отображаемый в обзоре, с помощью кнопок со стрелками. Текущая дата окрашена в красный цвет. Однако, если я изменю год, а затем вернусь к текущей дате, выделение исчезнет. Я не могу понять, как это изменить. Вы можете помочь мне? Здесь я покажу вам код: [code]import SwiftUI
struct MonthOverviewView: View { @State private var year: Int = Calendar.current.component(.year, from: Date()) // Aktuelles Jahr @State private var scrollProxy: ScrollViewProxy? = nil @State private var hasScrolledToToday = false // Verhindert mehrfaches Scrollen beim Laden der View private let calendar = Calendar.current private let daysOfWeek = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"] private let currentDay = Calendar.current.component(.day, from: Date()) private let currentMonth = Calendar.current.component(.month, from: Date()) private let currentYear = Calendar.current.component(.year, from: Date())
var body: some View { VStack { // Jahresnavigation mit Heute Button HStack { Button(action: { year -= 1 }) { Image(systemName: "chevron.left") .font(.title2) .padding() }
// Vermeide Tausendertrennung in der Jahreszahl Text("\(String(year))") .font(.largeTitle) .bold()
// Heute-Button für das Springen zum aktuellen Tag TodayButton { withAnimation { scrollProxy?.scrollTo("day-\(currentDay)-\(currentMonth)", anchor: .center) } year = currentYear } } .padding(.vertical, 10)
// Scrollbare Monatsübersicht für das gesamte Jahr ScrollViewReader { proxy in ScrollView { VStack(spacing: 40) { ForEach(1...12, id: \.self) { month in VStack { // Monatsüberschrift Text("\(calendar.monthSymbols[month - 1])") .font(.title) .bold()
// Tage des Monats anzeigen LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 20) { ForEach(getDaysInMonth(month: month, year: year), id: \.self) { day in if day != 0 { VStack(alignment: .leading) { // Highlight für den aktuellen Tag durch rote Ziffer Text("\(day)") .font(.body) // Kleinere Ziffern .bold() .foregroundColor(isToday(day: day, month: month, year: year) ? .red : .black) .padding(.bottom, 10) // Abstand zum unteren Bereich .padding(.leading, 5)
// Platzhalter für spätere Termine, größerer Bereich Rectangle() .fill(Color.clear) // Hintergrundfarbe entfernen .frame(height: 60) // Mehr Platz für Termine } .frame(minHeight: 120) // Vergrößerter Bereich für jeden Tag .border(Color.gray.opacity(0.2), width: 1) // Dezenter Rahmen .id("day-\(day)-\(month)") // Eindeutige ID für jeden Tag, damit genau dorthin gescrollt werden kann } else { Color.clear // Platzhalter für leere Felder } } } .padding(.horizontal) } } } .onAppear { scrollProxy = proxy // ScrollViewProxy speichern
// Nur einmalig beim ersten Laden der Ansicht zum aktuellen Tag scrollen if !hasScrolledToToday && year == currentYear { DispatchQueue.main.async { withAnimation { proxy.scrollTo("day-\(currentDay)-\(currentMonth)", anchor: .center) hasScrolledToToday = true // Verhindert erneutes Scrollen beim erneuten Aufrufen der View } } } } } } } }
// Funktion zur Berechnung der Tage des Monats func getDaysInMonth(month: Int, year: Int) -> [Int] { let dateComponents = DateComponents(year: year, month: month) guard let firstOfMonth = calendar.date(from: dateComponents), let range = calendar.range(of: .day, in: .month, for: firstOfMonth) else { return [] }
let numberOfDays = range.count let firstWeekday = calendar.component(.weekday, from: firstOfMonth) - 1 // Sonntag = 1, daher -1
var days = Array(repeating: 0, count: firstWeekday == 0 ? 6 : firstWeekday - 1) // Leerzeichen für die ersten Tage der Woche days += Array(1...numberOfDays) return days }
// Überprüft, ob der aktuelle Tag angezeigt wird func isToday(day: Int, month: Int, year: Int) -> Bool { return day == currentDay && month == currentMonth && year == currentYear } }
struct TodayButton: View { var action: () -> Void
var body: some View { Button(action: action) { Text("button_today") // .font(.headline) .padding(.horizontal) .padding(.vertical, 8) //.background(Color.blue.opacity(0.1)) .cornerRadius(10) } .padding(.trailing, 10) } } [/code] Что бы я ни пытался, когда я переключаюсь обратно с другого года на текущий год, функция isToday, похоже, не выполняется, и текущая дата больше не выделяется. Кажется, это всегда происходит, когда я меняю год, потому что, пока я прокручиваю только вверх или вниз в текущем году, выделение остается при первой загрузке страницы.