概要
やり方
- 「その月の日数」と「その月の最初の曜日」を取得
- LazyVGridで7日おきに改行
- その月の最初の曜日まではSpacer()で空白を挿入
- 「年と月」と「曜日」を表示
- 完成
まず、DateExtentionで「その月の日数」と「その月の最初の曜日」を取得します。
Date+
import Foundation
enum Weekday: Int, CaseIterable {
case sunday = 0
case monday = 1
case tuesday = 2
case wednesday = 3
case thursday = 4
case friday = 5
case saturday = 6
var name: String {
switch self {
case .sunday: return "日"
case .monday: return "月"
case .tuesday: return "火"
case .wednesday: return "水"
case .thursday: return "木"
case .friday: return "金"
case .saturday: return "土"
}
}
}
extension Date {
/// 月の日数を取得
var numberOfDaysInMonth: Int? {
let calendar = Calendar.current
guard let range = calendar.range(of: .day, in: .month, for: self) else {
return nil
}
return range.count
}
/// 月の最初の曜日を取得
var weekdayOfFirstDay: Weekday? {
let calendar = Calendar.current
let weekdayNumber = calendar.component(.weekday, from: self)
return Weekday(rawValue: weekdayNumber)
}
/// 年と月を取得
func yearAndMonth() -> String {
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month], from: self)
let year = components.year ?? 2000 // デフォルト値は2000年
let month = components.month ?? 1 // デフォルト値は1月
return String(format: "%04d年%02d月", year, month)
}
}
次にLazyVGridとForEachでカレンダーを作成します。
CalendarView
import SwiftUI
struct CalendarView: View {
let daysInMonth: Int = Date().numberOfDaysInMonth ?? 30
let firstDayOfMonth: Weekday = .saturday
var body: some View {
VStack {
Text(Date().yearAndMonth())
.padding()
HStack {
ForEach(0..<Weekday.allCases.count, id: \.self) { week in
Text(Weekday(rawValue: week)?.name ?? "a")
.frame(maxWidth: .infinity)
}
}
.padding(.horizontal, 5)
LazyVGrid(columns: Array(repeating: GridItem(), count: 7), spacing: 0) {
ForEach(0..<daysInMonth + firstDayOfMonth.rawValue, id: \.self) { day in
if day >= firstDayOfMonth.rawValue {
Text("\(day - firstDayOfMonth.rawValue + 1)")
.frame(maxWidth: .infinity)
.border(Color.gray)
} else {
Spacer()
}
}
}
.frame(maxWidth: .infinity)
.padding(.horizontal, 5)
}
}
}
#Preview {
CalendarView()
}
終わりに
今回はできる限りシンプルにカレンダーを自作してみました。もっとシンプルな方法があればコメントで教えてください。