Skip to content

Instantly share code, notes, and snippets.

@Jimmy-Prime
Created May 7, 2020 09:36
Show Gist options
  • Save Jimmy-Prime/8f6b5ebefcf7f0269c4cddeadbbd2326 to your computer and use it in GitHub Desktop.
Save Jimmy-Prime/8f6b5ebefcf7f0269c4cddeadbbd2326 to your computer and use it in GitHub Desktop.
import UIKit
class ViewController: UIViewController {
var yearView: UIView?
var currentYear: Int = 2020 {
didSet {
createYearView()
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "-", style: .plain, target: self, action: #selector(minus))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "+", style: .plain, target: self, action: #selector(add))
createYearView()
}
func createYearView() {
yearView?.removeFromSuperview()
let yearView = YearView(year: currentYear)
view.addSubview(yearView)
yearView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
yearView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
yearView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
yearView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
yearView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
])
self.yearView = yearView
}
@objc private func minus() {
currentYear -= 1
}
@objc private func add() {
currentYear += 1
}
}
class TitleGridView: UIView {
private let titleLabel = UILabel()
private let items: [[UIView]]
let rows: Int
let columns: Int
var interval: CGPoint = .zero
var spaceUnderTitle: CGFloat = 0
init(rows: Int, columns: Int, titleConfiguration: (UILabel) -> Void, itemCreator: (Int, Int) -> UIView) {
self.rows = rows
self.columns = columns
items = (0..<rows).map { row in
(0..<columns).map { column in
itemCreator(row, column)
}
}
super.init(frame: .zero)
titleConfiguration(titleLabel)
addSubview(titleLabel)
items.forEach { $0.forEach { addSubview($0) } }
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
titleLabel.frame = CGRect(x: 0, y: 0, width: frame.width, height: titleLabel.intrinsicContentSize.height)
let firstRowY = titleLabel.frame.maxY + spaceUnderTitle
let size = CGSize(
width: (frame.width - interval.x * CGFloat(columns - 1)) / CGFloat(columns),
height: (frame.height - firstRowY - interval.y * CGFloat(rows - 1)) / CGFloat(rows)
)
for (row, aRow) in items.enumerated() {
for (column, item) in aRow.enumerated() {
item.frame = CGRect(
x: CGFloat(column) * (size.width + interval.x),
y: CGFloat(row) * (size.height + interval.y) + firstRowY,
width: size.width,
height: size.height
)
}
}
}
}
class YearView: TitleGridView {
init(year: Int) {
let titleConfiguration = { (label: UILabel) in
label.font = .preferredFont(forTextStyle: .largeTitle)
label.text = String(year)
}
let itemCreator = { (row: Int, column: Int) in
MonthInYearView(year: year, month: row * 3 + column + 1)
}
super.init(rows: 4, columns: 3, titleConfiguration: titleConfiguration, itemCreator: itemCreator)
interval = CGPoint(x: 8, y: 4)
spaceUnderTitle = 4
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class MonthInYearView: TitleGridView {
init(year: Int, month: Int) {
let calendar = Calendar.current
let timeZone = TimeZone.current
let titleConfiguration = { (label: UILabel) in
label.font = .preferredFont(forTextStyle: .title2)
label.text = calendar.monthSymbols[month - 1]
}
let components = DateComponents(calendar: calendar, timeZone: timeZone, year: year, month: month)
let date = calendar.date(from: components)!
let firstWeekday = calendar.dateComponents(in: timeZone, from: date).weekday! - 1
let range = calendar.range(of: .day, in: .month, for: date)!
let itemCreator = { (row: Int, column: Int) -> UILabel in
let label = UILabel()
label.textAlignment = .center
label.font = .systemFont(ofSize: 10)
let day = row * 7 + column + 1 - firstWeekday
if range.contains(day) {
label.text = String(day)
}
return label
}
super.init(rows: 6, columns: 7, titleConfiguration: titleConfiguration, itemCreator: itemCreator)
interval = CGPoint(x: 4, y: 3)
spaceUnderTitle = 4
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment