๋ฐ์ํ
FSCalendar
์ปค์คํ ์บ๋ฆฐ๋๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
GitHub - WenchaoD/FSCalendar: A fully customizable iOS calendar library, compatible with Objective-C and Swift
A fully customizable iOS calendar library, compatible with Objective-C and Swift - GitHub - WenchaoD/FSCalendar: A fully customizable iOS calendar library, compatible with Objective-C and Swift
github.com
์์๋ณด๊ณ ์ ๋ฆฌํ๋๋ฐ ๊ฝค ์ค๋ ๊ฑธ๋ ธ๋๋ฐ ๋๊ธ ํ๋ฒ์ฉ๋ง ๋ฌ์์ฃผ์๋ฉด ํ์ด ๋ ๊ฑฐ ๊ฐ์ต๋๋น ใ ใ
Initializing
fileprivate var localCalendar = FSCalendar()
Delegate ์ฐ๊ฒฐ
// FSCalendarDelegate
localCalendar.delegate = self
// FSCalendarDataSource
localCalendar.dataSource = self
// FSCalendarDelegateAppearance
- FSCalendarDelegate, FSCalendarDataSource ๋ UICollectionViewDelegate์ UICollectionViewDataSource์ ์ฌ์ฉ๋ฒ์ด ์ ์ฌํจ(์ค์ ๋ก UICollectionView๋ก ๋์ด ์์)
- FSCalendarDelegateAppearance๋ก ์ปค์คํ ๊ฐค๋ฌ๋ฆฌ์ ์ธํ์ ์ค์ ํ ์ ์์
layout update
func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
self.view.layoutIfNeeded()
}
- ์๋์ผ๋ก ๋ ์ด์์์ด ์ ๋ฐ์ดํธ ๋์ง ์์ ๋ boundingRectWillChange ํธ์ถํด์ ์ ๋ฐ์ดํธ
Calendar ์ ์ฒด
- ์ค๋ ์ ํ ํด์งํ๊ธฐ
- default๋ก ์ค๋์ด ์ ํ๋์ด ์์
localCalendar.today = nil
- ์คํฌ๋กค ๊ธฐ๋ฅ ๋ง๊ธฐ
- default๋ก ๋ ์ง ๋ถ๋ถ์ ์คํฌ๋กค ํ๋ฉด ๋ค์์ด๋ ์ด์ ์๋ก ์ด๋๋จ
localCalendar.scrollEnabled = false
- UI ์ ๋ฐ์ดํธ
localCalendar.layoutIfNeeded()
- ๋๋ผ (ํ๊ตญ์ผ๋ก) ์ค์ ํ๊ธฐ
localCalendar.locale = Locale.init(identifier: "ko_KR")
// or
localCalendar.locale = Locale(identifier: "ko_KR")
- ์ด์ ํน์ ์ดํ ๋ ์ง ์๋จ๋๋ก ์์
- ๊ธฐ๋ณธ์ผ๋ก ์ด์ , ์ดํ ๋ ์ง๊ฐ ํ์ฌ ๋ฌ๋ ฅ์ ๋จ๊ฒ ๋์ด ์์
localCalendar.placeholderType = .none
- ์ ํ๋ ๋ ์ง ํ์๋ฅผ ๋๊ทธ๋ผ๋ฏธ์์ ๋ค๋ชจ๋ก ๋ณ๊ฒฝํ๊ธฐ
- ๋ ์ง๋ฅผ ์ ํํ๋ฉด ๋์ค๋ ๋๊ทธ๋ผ๋ฏธ๋ FSCalendarCell์ layer๋ก ๋ค์ด๊ฐ ์์ผ๋ฉฐ ๋ ์ง๊ฐ ํ์๋๋ titleLabel ๋ณด๋ค ์์ ์์ญ์ผ๋ก ๊ทธ๋ ค์ง
- layer์ ํฌ๊ธฐ๋ฅผ ํค์ฐ๋๋ผ๋ ์ ์ฌ์ด์ ์ฌ๋ฐฑ์ด ์์ผ๋ฏ๋ก ์ฃผ์ ๊ทธ ๋๋ inserBy๋ก inset์ ํค์ ์ค
localCalendar.appearance.borderRadius = 0.0
Header Title
- ๋ฌ๋ ฅ์์ ์์ผ ์์ ๋ ์ง๊ฐ ํ์๋๋ ์์ญ์ด header๋ก ๋ถ๋ฆผ
- ์์ง header title์ ๋งจ ์์ ๋ถ์ด๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ์ ์ด ์ฌ์ง์ snapkit์ผ๋ก ๋ค๋ฅธ ๋ทฐ๋ ์ฎ์ด์ ์์ ์๋ฆฌ๋๋ก ๋ง๋ ๊ฒ
- ํค๋ ๋์ด
localCalendar.headerHeight = 48
- ํค๋ ํ์ดํ ๋ ์ง ๋ฐ์ดํฐ ํฌ๋ฉง ์ง์
localCalendar.appearance.headerDateFormat = "YYYY๋
MM์"
- ํค๋ ํ์ดํ ์์
localCalendar.appearance.headerTitleColor = .red // UIColor
- ํค๋ ํ์ดํ ํฐ๋
localCalendar.appearance.headerTitleFont = UIFont(name: UIFont.NormalFont.medium, size: 18)!
- ํค๋ ํ์ดํ ์ ๋๋ฉ์ด์
์ ๊ฑฐ
- default๋ก ๋ฌ๋ ฅ์ด ์ด์ ์ด๋ ๋ค์ ๋ฌ๋ก ๋์ด๊ฐ๋ฉด ํค๋ ํ์ดํ์์ ์ด์ ๋ฌ๋ ฅ์ ํค๋ ํ์ดํ์ ์ํ๊ฐ์ด ์กฐ์ ๋๋ฉด์ ์ฌ๋ผ์ง๊ฑฐ๋ ๋ํ๋๋ ์ ๋๋ฉ์ด์ ์ด ์์
localCalendar.appearance.headerMinimumDissolvedAlpha = 0.0
Weekday(์์ผ)
- ์์ผ ์์ญ ๋์ด ์ค์
localCalendar.weekdayHeight = 46
- ์์ผ ์์ญ ํ ์คํธ ์ปฌ๋ฌ
localCalendar.appearance.weekdayTextColor = .bentleyColor(.black70)
- ์์ผ ์์ญ ํฐํธ
localCalendar.appearance.weekdayFont = UIFont(name: UIFont.NormalFont.medium, size: 14)!
Day
- ๋ ์ง ํฐํธ ๋ณ๊ฒฝ
localCalendar.appearance.titleFont = UIFont(name: UIFont.NormalFont.medium, size: 14)!
FSCalendarDataSource
- ์ต์ ๋ ์ง ์ง์
- ์์ ์ฝ๋๋ ์ค๋ ๋ถํฐ ์์ํ๋๋ก ์ง์ ํ๋ ๊ฒ
func minimumDate(for calendar: FSCalendar) -> Date {
return Date()
}
- ์ต๋ ๋ ์ง ์ง์
- ์์ ์ฝ๋๋ ์ด๋ฒ๋ฌ ํฌํจ 3๊ฐ์ ๊น์ง๋ง ๋์ค๋๋ก ์ง์
func maximumDate(for calendar: FSCalendar) -> Date {
let currentCaledar = Calendar(identifier: .gregorian)
let startComponents = currentCaledar.dateComponents([.year, .month], from: Date())
let startOfMonth = currentCaledar.date(from: startComponents)!
var endComponents = DateComponents()
let limitDate = Singleton.sharedObject.initData?.reservationLimitDate
endComponents.month = Int(limitDate ?? "3") ?? 3
endComponents.day = -1
return Calendar(identifier: .gregorian).date(byAdding: endComponents, to: startOfMonth)!
}
FSCalendarDelegate
- layout update
- FSCalendar๋ ์๋์ผ๋ก ํฌ๊ธฐ๊ฐ ์ง์ ๋์ง ์๊ธฐ ๋๋ฌธ์ AutoLayout, frame์ผ๋ก ์ค์ ํ ๋ค ์ ๋ฐ์ดํธ ํด์ค์ผ ํจ (ํ ์คํธ ํด๋ณธ ๊ฒฐ๊ณผ ์๋ ์๋ ์ฐจ์ด ์์)
func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
self.view.layoutIfNeeded()
}
- ๋ ์ง ์ ํ didSelect delegate
- ๋ ์ง ์ ํ ํ ์ฒ๋ฆฌํ ์ด๋ฒคํธ๋ฅผ ์ง์ ํด ์ค ์ ์์. ์ ํ๋ ๋ ์ง๋ date ๋ณ์์ ๋ด๊ฒจ์ ๋์ด
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
print(date)
}
FSCalendarAppearance
- ํน์ ์กฐ๊ฑด์ผ ๋ ๋ ์ง ์์ ๋ณ๊ฒฝ
- ์์ ์ฝ๋์๋ holiday ๋ผ๋ ์กฐ๊ฑด์ ๋ฐ๋ผ ํด๋น ๋ ์ง์ ์์์ ๋ณ๊ฒฝํ๋ ๊ฒ
func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, titleDefaultColorFor date: Date) -> UIColor? {
if holiday {
return .red
} else {
return .black
}
}
CustomCell
- ํ์ฌ ๋ฌ๋ ฅ์ ์๋ cell ๊ณผ date, position ์ป์ด์ค๊ธฐ
localCalendar.visibleCells().forEach { (cell) in
let date = self.localCalendar.date(for: cell)
let position = self.localCalendar.monthPosition(for: cell)
// custom configuration
// self.configureCell(cell, for: date, at: position)
}
- FSCalendarDataSource ์์ ์ปค์คํ ์ ๊ณผ identifier ์ง์
func calendar(_ calendar: FSCalendar, cellFor date: Date, at position: FSCalendarMonthPosition) -> FSCalendarCell {
let cell = calendar.dequeueReusableCell(withIdentifier: "cell", for: date, at: position)
return cell
}
- register cell
localCalendar.register(CalendarCollectionViewCell.self, forCellReuseIdentifier: "cell")
- ์บ๋ฆฐ๋ display ๋ ๋ ์ต์ด ์ค์
- ์ปค์คํ ์ ์ด ๋ก๋ ๋ ๋ ์ํ๋ฅผ ์ง์ ํ์ฌ UI ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ
func calendar(_ calendar: FSCalendar, willDisplay cell: FSCalendarCell, for date: Date, at monthPosition: FSCalendarMonthPosition) {
// custom configuration
// configureCell(cell, for: date, at: monthPosition)
}
- configure cell
- ์์ ์ฝ๋
func configureCell(_ cell: FSCalendarCell?, for date: Date?, at position: FSCalendarMonthPosition) {
guard let date = date else {
return
}
dateFormatter.dateFormat = "yyyy-MM-dd"
for availableDate in availableDateList {
let dateString = dateFormatter.string(from: date)
if dateString == availableDate.day {
if availableDate.holiday ?? true {
cell?.isUserInteractionEnabled = false
}
}
}
let selectedDateString = dateFormatter.string(from: date)
let todayDateString = dateFormatter.string(from: Date())
let calendarCell = cell as! CalendarCollectionViewCell
if selectedDateString == todayDateString {
calendarCell.selectionType = localCalendar.selectedDate == date ? .todaySelect : .todayDiselect
} else {
calendarCell.selectionType = localCalendar.selectedDate == date ? .select : .normal
}
}
- custom cell ์์ฑ
class CalendarCollectionViewCell: FSCalendarCell {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init!(coder aDecoder: NSCoder!) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
override func configureAppearance() {
super.configureAppearance()
}
}
728x90
๋ฐ์ํ
'๐ iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS/Swift] UICollectionView Dynamic Height with AutoConstraint (0) | 2023.03.25 |
---|---|
[iOS/Xcode] Pod file not found ์ด์ (0) | 2023.03.23 |
[Swift] ๊ณ ์ฐจ ํจ์ CompactMap (2) | 2023.03.09 |
[iOS/Swift] Dynamic Link ์ ๋ฆฌ (0) | 2023.03.08 |
[iOS/Swift] Firebase Remote Notification ์ ๋ฆฌ (0) | 2023.03.08 |
๋๊ธ