見出し画像

SwiftUIでいこう! - カレンダー 3

実際のカレンダーの日付を作っていきます。今の月についての情報を変数に入れて使えるようにしていきます。参考にしている動画はこちら

let daysInMonth ・・・ その月の日数
let firstDayOfMonth ・・・ 年、月
let startingSpaces ・・・ 1日の曜日(1日以前のスペースを入れる)
let prevMonth ・・・ 前の月
let daysInPrevMonth ・・・ 前の月の日数

 let daysInMonth = CalendarHelper().daysInMonth(dateHolder.date)
 let firstDayOfMonth = CalendarHelper().firstOfMonth(dateHolder.date)
 let startingSpaces = CalendarHelper().weekDay(firstDayOfMonth)
 let prevMonth = CalendarHelper().minusMonth(dateHolder.date)
 let daysInPrevMonth = CalendarHelper().daysInMonth(prevMonth)

CalendarHelperにメソッド追加。

    func daysInMonth(_ date: Date) -> Int{
      let range = calendar.range(of: .day, in: .month, for: date)!
      return range.count
    }
    
    func dayOfMonth(_ date: Date) -> Int
      let components = calendar.dateComponents([.day], from: date)
      return components.day!
    }
    
    func firstOfMonth(_ date: Date) -> Date{
      let components = calendar.dateComponents([.year, .month], from: date)
      return calendar.date(from: components)!
    }
    
    func weekDay(_ date: Date) -> Int{
      let components = calendar.dateComponents([.weekday], from: date)
      return components.weekday! - 1
    }


カレンダーを表示させる仕組みを作っていきます。

日付を取得すると数字を受け取ることになるので文字列に変更する構造体を作ります。
enumでMonthTypeを定義します。カレンダーの本体をCurrent、前後をPrevious、Nextとし使い分けができるようにしておきます。

struct MonthStruct
{
    var monthType: MonthType
    var dayInt : Int
    func day() -> String
    {
        return String(dayInt)
    }
}

enum MonthType
{
    case Previous
    case Current
    case Next
}

カレンダーの実際の表記する方法としてデータをもとに数字を配置できるように"CalendarCell"を定義します。

import SwiftUI

struct CalendarCell: View
{
    @EnvironmentObject var dateHolder: DateHolder
    let count : Int
    let startingSpaces : Int
    let daysInMonth : Int
    let daysInPrevMonth : Int
    
    var body: some View
    {
        Text(monthStruct().day())
            .foregroundColor(textColor(type: monthStruct().monthType))
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    func textColor(type: MonthType) -> Color
    {
        return type == MonthType.Current ? Color.white : Color.gray
    }
    
    func monthStruct() -> MonthStruct
    {
        let start = startingSpaces       
        let day = count - start
        return MonthStruct(monthType: MonthType.Current, dayInt: day)
    }
}

これで表示してみると

前の月と

        if(count <= start){
            let day = daysInPrevMonth + count - start
            return MonthStruct(monthType: MonthType.Previous, dayInt: day)
        }

後の月を入れ込むために追加します。

  else if (count - start > daysInMonth) {
            let day = count - start - daysInMonth
            return MonthStruct(monthType: MonthType.Next, dayInt: day)
        }

CalendarCellの全コードは

import SwiftUI

struct CalendarCell: View
{
    @EnvironmentObject var dateHolder: DateHolder
    let count : Int
    let startingSpaces : Int
    let daysInMonth : Int
    let daysInPrevMonth : Int
    
    var body: some View
    {
        Text(monthStruct().day())
            .foregroundColor(textColor(type: monthStruct().monthType))
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    func textColor(type: MonthType) -> Color
    {
        return type == MonthType.Current ? Color.white : Color.gray
    }
    
    func monthStruct() -> MonthStruct
    {
        let start = startingSpaces == 0 ? startingSpaces + 7 : startingSpaces
        if(count <= start)
        {
            let day = daysInPrevMonth + count - start
            return MonthStruct(monthType: MonthType.Previous, dayInt: day)
        }
        else if (count - start > daysInMonth)
        {
            let day = count - start - daysInMonth
            return MonthStruct(monthType: MonthType.Next, dayInt: day)
        }
        
        let day = count - start
        return MonthStruct(monthType: MonthType.Current, dayInt: day)
    }
}

これを利用して"ContentView"に入れ込みます。

 var calendarGrid: some View{
        VStack(spacing: 1){
            
            let daysInMonth = CalendarHelper().daysInMonth(dateHolder.date)
            let firstDayOfMonth = CalendarHelper().firstOfMonth(dateHolder.date)
            let startingSpaces = CalendarHelper().weekDay(firstDayOfMonth)
            let prevMonth = CalendarHelper().minusMonth(dateHolder.date)
            let daysInPrevMonth = CalendarHelper().daysInMonth(prevMonth)
        
           ForEach(0..<6){ row in
               HStack(spacing: 1){
                    ForEach(1..<8){ column in 
                        let count = column + (row * 7)
                        CalendarCell(count: count, startingSpaces:startingSpaces, daysInMonth: daysInMonth, daysInPrevMonth: daysInPrevMonth)
                            .environmentObject(dateHolder)
                    }
               }
            }
        } .frame(maxHeight: .infinity)

これで、うまく表示できるようになりました。




この記事が気に入ったらサポートをしてみませんか?