うるおいらんど

アプリ開発やサイト制作のメモとか。

【Swift3】連続型カレンダーを実装してみた【UICollectionView】

魚ライン
魚ライン

UICollectionViewを用いてこんな感じの連続したカレンダーを作ってみました。



 

決められた日付から現在の月のカレンダーまでを表示しています。

iPhoneに元々入っているカレンダーのように、延々と遡れるタイプではないですが紹介していきます。

 

UICollectionViewを設置する

カレンダーの日付をUICollectionViewを用いて表示します。

まずはUICollectionViewを設置。

 

UICollectionViewの細かいことは割愛します。

UICollectionViewFlowLayoutについては、「【Swift】UICollectionViewFlowLayoutの余白調整について」ちょろっと書いていますのでよかったらどうぞ。

 

セルの余白とコレクションビューの行数を用意しています。

 

カスタムセルを作る

上記のままだとCalendarCellというものはないよと言われるので作成します。

File > New > File より

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-4-42-26

 

Source > Cocoa Touch Classを選択

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-4-42-44

 

Subclass of:UICollectionViewCellに設定し、CalendarCellを作成

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-4-43-29

 

サブクラスがUICollectionViewCellのCalendarCellにラベル等を乗せていきます。

 

このCalendarCellでとりあえずラベルの位置や、ラベルを置くことを決めています。

とりあえずセルの型を作って置いて、ラベルのテキストは

の中で書いていきます。

 

日付を取得しよう

日付の取得は、NSDateのサブクラスであるDateManagerを作成してそこに書いていきます。

先ほどと同様の手順です。

File > New > File

Source > Cocoa Touch Class

Subclass of :NSDateにしたDateManagerを作成

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-5-02-29

 

この中に色々メソッドを書いていきます。

 

とりあえずDateManagerの全体コードから

 

見辛かったらごめんなさい(´・ω・`)

 

1つ1つのメソッドを見ていきます。

まずセルの総数を返すメソッドです。

 

マーカーを引いた部分ですが、少し分かりづらいのでちょっと画像で説明すると



この判定を行なっています。

指定した月と現在の月が同じ場合(iが0のとき)はすべての週を表示します。

 

1週間ごとでなく、単純に日付の個数を数えてもいいかもしれません。

 

こうすると、一番最後の月(現在の月)の週最後に次の月の日付が表示されなくなります。

(11月30日が水曜日とすると、木曜日以降の12月1日2日3日の表示がされなくなる)

 

 

次に指定された月の初日を返すメソッドを見ていきます。

 

2016年11月29日(date)を渡された場合は、2016年11月1日(firstDateMonth)を返すというメソッドです。

はい。

 

次に表記する日にちを取得するメソッドです。

 

dateComponet.day の部分は

例えばカレンダーを始めた月が2016年11月とします。

row = 0 ordinalityOfFirstDay = 3 (11月1日が火曜日)のとき

dateComponent.day = 0 – (3 – 1)  = -2となります。

この場合すべての基準の日付が2016年11月1日になり、そこから何日増えているかを計算して日付を取得しています。

-2でも、基準から-2日した日付(10月30日)が取得できます。

 

 

次にこの取得した日付をstring型に変換するメソッドを見ていきます。

 

先ほどのメソッドを呼び出してDateFormatterで実際にカレンダーに入れるテキストを作成しています。

 

同様に、月日を返すメソッドも用意しておきます。

 

これで日付を取得する準備ができました。

 

日付をCollectionViewに表示しよう

それではDateManagerに作成したメソッドを使用していきます。

UICollectionViewを設置したViewControllerを開きます。

まずはDateManagerを取得。

これはViewController内に書いておけば楽かな・・・?

 

とりあえずViewController内に最初の月を書いておきます。

 

適当に現在より前の日付を設定しておきます。

 

セルの総数を書き直します。

 

セルの設定をしていきます。

 

これでとりあえずカレンダーの見た目になりました!

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-7-11-15

 

しかしこのままでは今が何月かわかりません。

 

年月を表示しよう

まずは年月を表示するラベルを用意しておきます。

 

cellにtagをつけます。

 

これでcellには「201611」のような年と月がくっついた数字タグがつきました。

 

スクロールを監視して、現在表示されている日数が多い月の表示をするようにしていきます。

 

まず

の部分で現在表示されているセルのうち、フレーム内に全ておさまっているセルを取得しています。

半分だけ表示されている、といったセルは取得されません。

 

この先は表示されているセルがない場合はクラッシュするので判定をしておきます。

さらにこの中からセルのタグを別の配列にしておきます。

 

1月2月3月と奇数偶数奇数・・・となっているのを利用して、現在どちらが多いかを判定していきます。

1月と2月の間にいるときは、見えているのは1月または2月のはずなので、どちらか多い方を取り出してmonthにいれています。

 

そして桁数によって、String型に変換するときに何桁分を年にするか、月にするかを判定しています。

 

numberOfDigit(month:Int)ではmonthが何桁かを取得しています。

 

スクロールすると月が変わるようになりますが、最初に表示する月が決められていないのでセルのindexPath.rowが6の位置の月を表示するようにしておきます。(0にすると前の月が表示される)

ラベルの部分を付け足します。

先ほどと同様に桁数で判定しています。

 

これでとりあえず連続カレンダー自体は完成です。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-29-7-57-43

ここからはちょっとおまけ。

 

セルの上下左右決められた位置にだけ線を引こう

先ほどの画像では月の区切りが分かりづらいです。一番最初の動画のように線を引いていきます。

デフォルトの仕様ではborderを設定すると、上下左右全てに線が入ってしまいます。

【Swift】UIViewの各辺を指定してborderをつけるExtension

こちらの記事を参考にさせていただきました。

というかSwift3に対応させただけなんですけども。

 

 

こちらをCollectionViewを設置したViewControllerに追加します。

セルにborderをつけます。

 

このとき、枠線を引かない時(else部分)を追加していないと大変なことになります・・・・。

セルを再利用しているので、枠線が再利用され場所でもそのまま表示されてしまいます。

 

1日は上左に、2~7日は上にのみ枠線を表示する設定にするとちょうど区切りができます。

 

起動時に現在の月を表示する

これは実はちょっとあんまりうまくいってないんですけど、無理矢理解決させたのでちょこっと書いておきますね。

このカレンダーの場合、1番下が現在の月になっています。

なので、とりあえず起動時に1番下までスクロールして現在の月を表示するようにしてみました。

 

 

githubとかにコードあげたほうが本当はいいんでしょうけど、まだ使い方がわかってないのでとりあえずそのまま全体コードもここに書いておきます。

 

全体コード

ViewController.swift

 

DateManager.swift

 

CalendarCell.swift

 

 

コメントつけたままでちょっと邪魔かもしれませんがこのままで失礼します。

 

 

単純に書き方の問題だったり、改善法だったりありましたら教えていただけると嬉しいです。

ではでは

 

参考記事

【Swift】Calendarアプリを作る

その他にもたくさんの記事を参考にさせていただきましたが、ちょっとあらゆるところで調べててどの記事だったかもわからなくなってしまっていました。すみません。

魚ライン
モッピー!お金がたまるポイントサイト
魚ライン

Swiftの記事一覧を見る

コメント

コメントは認証制です。詳しくは下記の注意をお読みください。

コメントを残す

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

魚ライン 魚ライン