Created
April 12, 2018 07:41
-
-
Save uruly/7060300fc64538448fe0ba0926faf682 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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!) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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