Skip to content

Instantly share code, notes, and snippets.

@uruly
Created April 12, 2018 07:41
Show Gist options
  • Save uruly/7060300fc64538448fe0ba0926faf682 to your computer and use it in GitHub Desktop.
Save uruly/7060300fc64538448fe0ba0926faf682 to your computer and use it in GitHub Desktop.
import UIKit
class CalendarCell: UICollectionViewCell {
public var textLabel:UILabel!
required init(coder aDecoder:NSCoder){
super.init(coder: aDecoder)!
}
override init(frame:CGRect){
super.init(frame:frame)
//UILabelを生成
textLabel = UILabel()
textLabel.frame = CGRect(x:0,y:0,width:self.frame.width,height:self.frame.height)
textLabel.textAlignment = .center
self.contentView.addSubview(textLabel!)
}
}
import UIKit
@objc protocol CalendarViewDelegate {
func changeMonth(_ text:String)
}
class CalendarView: UICollectionView{
//セルの余白
let cellMargin:CGFloat = 2.0
let dateManager = DateManager()
//1週間に何日あるか(行数)
let daysPerWeek:Int = 7
var startDate:Date!
var calendarDelegate:CalendarViewDelegate!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: layout)
self.register(CalendarCell.self, forCellWithReuseIdentifier: "collectCell")
self.delegate = self
self.dataSource = self
self.backgroundColor = .white
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleCell = self.visibleCells.filter{
return self.bounds.contains($0.frame)
}
var visibleCellTag = Array<Int>()
if(visibleCell != []){
visibleCellTag = visibleCell.map{$0.tag}
//月は奇数か偶数か 割り切れるものだけを取り出す
let even = visibleCellTag.filter{
return $0 % 2 == 0
}
let odd = visibleCellTag.filter{
return $0 % 2 != 0
}
//oddかevenの多い方を返す
let month = even.count >= odd.count ? even[0] : odd[0]
//桁数によって分岐
let digit = numberOfDigit(month: month)
var text = ""
if(digit == 5){
text = String(month / 10) + "年" + String(month % 10) + "月"
}else if(digit == 6){
text = String(month / 100) + "年" + String(month % 100) + "月"
}
if calendarDelegate != nil {
calendarDelegate.changeMonth(text)
}
}
}
func numberOfDigit(month:Int) -> Int{
var num = month
var cnt = 1
while(num / 10 != 0){
cnt = cnt + 1
num = num / 10
}
return cnt
}
}
extension CalendarView:UICollectionViewDelegate {
//選択した時
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
}
extension CalendarView: UICollectionViewDataSource {
//セクションの数
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
//セルの総数
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dateManager.cellCount(startDate:startDate)
}
//セルの設定
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:CalendarCell = collectionView.dequeueReusableCell(withReuseIdentifier:"collectCell",for:indexPath as IndexPath) as! CalendarCell
//土曜日は赤 日曜日は青 にテキストカラーを変更する
if(indexPath.row % 7 == 0){
cell.textLabel.textColor = UIColor.red
}else if(indexPath.row % 7 == 6){
cell.textLabel.textColor = UIColor.blue
}else{
cell.textLabel.textColor = UIColor.gray
}
cell.tag = Int(dateManager.monthTag(row:indexPath.row,startDate:startDate))!
//セルの日付を取得し
cell.textLabel.text = dateManager.conversionDateFormat(row:indexPath.row,startDate:startDate)
//セルの日付を取得
let day = Int(dateManager.conversionDateFormat(row:indexPath.row,startDate:startDate!))!
if(day == 1){
cell.textLabel.border(positions:[.Top,.Left],borderWidth:1,borderColor:UIColor.black)
}else if(day <= 7){
cell.textLabel.border(positions:[.Top],borderWidth:1,borderColor:UIColor.black)
}else{
cell.textLabel.border(positions:[.Top],borderWidth:0,borderColor:UIColor.white)
}
return cell
}
}
extension CalendarView: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView:UICollectionView,layout collectionViewLayout:UICollectionViewLayout,minimumLineSpacingForSectionAt section:Int) -> CGFloat{
return cellMargin
}
func collectionView(_ collectionView:UICollectionView,layout collectionViewLayout:UICollectionViewLayout,minimumInteritemSpacingForSectionAt section:Int) -> CGFloat{
return cellMargin
}
//セルのサイズを設定
func collectionView(_ collectionView:UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAt indexPath:IndexPath) -> CGSize{
let numberOfMargin:CGFloat = 8.0
let width:CGFloat = (collectionView.frame.size.width - cellMargin * numberOfMargin) / CGFloat(daysPerWeek)
let height:CGFloat = width * 2.0
return CGSize(width:width,height:height)
}
}
import UIKit
class CalendarViewController: UIViewController {
var monthLabel:UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let barHeight = UIApplication.shared.statusBarFrame.size.height
let width = self.view.frame.width
let height = self.view.frame.height
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsetsMake(0,0,0,0)
//コレクションビューを設置していくよ
let calendarFrame = CGRect(x:0,y:barHeight + 50,width:width,height:height - barHeight - 50)
let calendarView = CalendarView(frame: calendarFrame, collectionViewLayout: layout)
calendarView.calendarDelegate = self
self.view.addSubview(calendarView)
let startMonth = 10
let startYear = 2015
var components = Calendar.current.dateComponents([.year ,.month, .day], from:Date())
components.day = 1
components.month = startMonth
components.year = startYear
let startDate = Calendar.current.date(from: components)
calendarView.startDate = startDate
//年月ラベル
monthLabel = UILabel()
monthLabel.frame = CGRect(x:0,y:0,width:width,height:100)
monthLabel.center = CGPoint(x:width / 2,y:50)
monthLabel.textAlignment = .center
monthLabel.text = "\(startYear)年\(startMonth)月"
self.view.addSubview(monthLabel)
}
}
extension CalendarViewController: CalendarViewDelegate {
func changeMonth(_ text: String) {
self.monthLabel.text = text
}
}
import UIKit
class DateManager {
//現在の日付
private var selectedDate = Date()
//1週間に何日あるか
private let daysPerWeek:Int = 7
//セルの個数(nilが入らないようにする)
private var numberOfItems:Int = 0
/* 指定した月から現在の月までのセルの数を返すメソッド
** 引数 -> startDate 指定した月 カレンダーを始める月
** return -> セルの総数
*/
func cellCount(startDate:Date) -> Int{
//startDate(1番最初の日時)の年月を取り出す
let startDateComponents = Calendar.current.dateComponents([.year ,.month], from:startDate)
//currentDate(現在の日時)の年月を取り出す
let currentDateComponents = Calendar.current.dateComponents([.year ,.month], from:selectedDate)
//startDateとcurrentDateが何ヶ月離れているか fromとtoの差を取り出す
let components = Calendar.current.dateComponents([.year,.month], from: startDateComponents, to: currentDateComponents)
//startDateとcurrentDateが何ヶ月離れているか計算する
let numberOfMonth = components.month! + components.year! * 12
//1月ずつ何日あるか見ていく
for i in 0 ..< numberOfMonth + 1{
//monthをiに設定したdateComponentsを用意し、startDateからi月分足した日付(date)を取得する
var dateComponents = DateComponents()
dateComponents.month = i
let date = Calendar.current.date(byAdding: dateComponents, to: startDate)
//取得した月に週がいくつあるかを取得 in(その月)にof(週)が何個あるか
let dateRange = Calendar.current.range(of: .weekOfMonth, in: .month, for: date!)
//月の初日が何曜日かを取得 日曜日==1
let ordinalityOfFirstDay = Calendar.current.ordinality(of: .day, in: .weekOfMonth, for: firstDateOfMonth(date:date!))
//その月の始まりが日曜日かどうかで場合分け
if(ordinalityOfFirstDay == 1 || i == 0){
numberOfItems = numberOfItems + dateRange!.count * daysPerWeek
}else{
numberOfItems = numberOfItems + (dateRange!.count - 1) * daysPerWeek
}
}
//セルの総数を返す
return numberOfItems
}
/* 指定された月の初日を取得 */
func firstDateOfMonth(date:Date) -> Date{
//渡された日時から日にちを1にした日付を返す
var components = Calendar.current.dateComponents([.year ,.month, .day], from:date)
components.day = 1
let firstDateMonth = Calendar.current.date(from: components)
return firstDateMonth!
}
/* 表記する日にちの取得 週のカレンダー
** 引数 row -> UICollectionViewのIndexPath.row
** startDate -> 指定した月 カレンダーを始める月
** return date -> セルに入れる日付
*/
func dateForCellAtIndexPathWeeks(row:Int,startDate:Date) -> Date{
//始まりの日が週の何番目かを計算(日曜日が1) 指定した月の初日から数える
let ordinalityOfFirstDay = Calendar.current.ordinality(of: .day, in: .weekOfMonth, for: firstDateOfMonth(date:startDate))
var dateComponents = DateComponents()
dateComponents.day = row - (ordinalityOfFirstDay! - 1)
//計算して、基準の日から何日マイナス、加算するか dateComponents.day = -2 とか
let date = Calendar.current.date(byAdding:dateComponents,to:firstDateOfMonth(date:startDate))
return date!
}
/* 表記の変更 これをセルを作成する時に呼び出す
引数 row -> UICollectionViewのIndexPath.row
startDate -> 指定した月 カレンダーを始める月
return String -> セルに入れる日付をString型にしたもの
*/
func conversionDateFormat(row:Int,startDate:Date) -> String{
let cellDate = dateForCellAtIndexPathWeeks(row: row,startDate:startDate)
let formatter = DateFormatter()
formatter.dateFormat = "d"
return formatter.string(from: cellDate)
}
//月を返す
func monthTag(row:Int,startDate:Date) -> String{
let cellDate = dateForCellAtIndexPathWeeks(row: row,startDate:startDate)
let formatter = DateFormatter()
formatter.dateFormat = "YM"
return formatter.string(from:cellDate)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment