1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI】超簡単なカレンダーを自作

Last updated at Posted at 2024-05-12

概要

今回は以下のようなカレンダーを自作します。

やり方

  1. 「その月の日数」と「その月の最初の曜日」を取得
  2. LazyVGridで7日おきに改行
  3. その月の最初の曜日まではSpacer()で空白を挿入
  4. 「年と月」と「曜日」を表示
  5. 完成

まず、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()
}

終わりに

今回はできる限りシンプルにカレンダーを自作してみました。もっとシンプルな方法があればコメントで教えてください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?