이번주는 캘린더의 UI 그리기 편입니다.
고려해야 할 내용은 주로
1) 매 달 1일이 무슨 요일에 시작하는지
2) 매 달 해당 일수를 어떻게 그려야 하는지
입니다. Xib와 CollectionView로 구성하였습니다. 궁금한 점이나 오류가 있다면 댓글 부탁드립니다!
* Xib : CollectionView, CollectionView Cell.
1) 매달 1일이 무슨 요일에 시작하는지
저번 편에서 언급한 바와 같이, 해당 요일의 인덱스는 .weekday 컴포넌트로,
Calendar.current.component(.weekday, from: Date()) 와 같이 받아올 수 있었습니다.
리턴형은 Int로, 일요일은 1부터, 토요일은 7이었습니다. 예를 들면 2020-04-01은 4(수요일) 이였습니다.
4월은 30일까지밖에 없으므로,
4월의 일 수 : 30일
첫주의 일 수 : 4일 (수요일부터 시작)
리턴받는 CollectionView Cell의 개수 : 30일 + 1일 이전의 인덱스 3개 -> 33개
위와 같은 알고리즘으로 뷰를 그려보았습니다.
2) 매 달, 해당 일 수를 어떻게 그려야 하는지
컬렉션뷰의 Item의 개수 리턴은 다음과 같이 받았습니다.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numOfDaysInMonth[currentMonthIndex] + firstWeekDayOfMonth - 1
}
기존 Month배열에, 첫 주의 Index - 1 (Index가 1부터 시작하기 때문에 -1)
4월의 Item 개수는 30일 + (첫 주의 Index 4 - 1) 까지 33을 리턴받게 됩니다.
하지만, 33개의 셀을 모두 그려낼 필요는 없습니다. 4월은 30일까지 존재하기 때문에 30개의 Item만 그려내면 됩니다.
cell.isHidden 속성을 이용하였습니다.
매 달의 IndexPath.item과, 매 달의 첫 주의 Index를 비교합니다.
4월의 경우, IndexPath.item과 numOfDaysInMonth을 비교합니다. 4월은 수요일부터 시작하므로 리턴은 4(수요일)
앞에서부터 3개는 그려낼 필요가 없다는 뜻입니다.
0부터 시작하는 IndexPath는 0,1,2는 버려야 합니다. 3부터 그려내야 하므로
if indexPath.item <= firstWeekDayOfMonth - 2 {
cell.isHidden = true
return cell
}
다음과 같이 계산하면 셀의 개수를 알맞게 그려낼 수 있게 됩니다.
3) Tips
공부하다 보니, 재밌게 뷰를 그릴 수 있는 방법...(?)을 알게 되어서 끄적이려고 합니다. 언젠가 써먹을 수 있을까 해서.
CellForItemAt을 다음과 같이 커스텀할 수 있습니다.
원래는
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnyCell", for: indexPath) as? AnyCell
와 같이 하는 형태에서,,,,
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = DateCollectionViewCell.cellForCollectionView(collectionView: collectionView, indexPath: indexPath)
~
}
DateCollectionViewCell (cell이름) .cellForCollectionView (만든 함수)를 쓰더라.
저렇게 사용하면 좋은 점 : Xib를 내 의도대로 사용할 수 있었습니다.
class func cellForCollectionView(collectionView: UICollectionView, indexPath: IndexPath) -> DateCollectionViewCell {
let kDateCollectionViewCellIdentifier = "kDateCollectionViewCellIdentifier"
collectionView.register(UINib(nibName: "DateCollectionViewCell", bundle: Bundle.main), forCellWithReuseIdentifier: kDateCollectionViewCellIdentifier)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kDateCollectionViewCellIdentifier, for: indexPath) as! DateCollectionViewCell
return cell
}
CollectionViewCell 내부에 다음과 같이 선언 후 사용하면 Xib가 Xib 안에 잘 걸립니다.
코드는 이전 편 깃헙 링크에 있습니다!
달력은 힘든 일이라는걸 알았고, 달력 플젝도 엎어져서 필요 없게 되었지만,
또 실력이 성장했으리라 생각하며,,,
'iOS' 카테고리의 다른 글
[iOS] 화면전환 애니메이션 커스텀하기 - CGAffineTransform, animateTransition [1] (3) | 2020.05.15 |
---|---|
[iOS] SideBar (3) | 2020.05.09 |
[iOS] Calendar (1) (0) | 2020.04.25 |
[iOS] LinkPresentation (0) | 2020.04.18 |
[iOS, Crecker] ActionSheet, (0) | 2020.04.11 |