Dimming
Dim View
- 스크롤에 따라 뷰의 가시성을 조절하는 뷰를 만드는 방법을 설명한다.
1. 뷰로부터 첫번째 셀까지의 Inset 구하기(위쪽 여백 구하기)
collection 뷰의 높이
에서 첫번째 셀의 높이
, safeAreaInset의 top
, safeAreaInset의 bottom
, 그리고 section inset
을 빼주어야 한다.
2. 해당하는 뷰에 구한 Inset 설정하기
3. selectItem으로 해당 셀로 이동
- Inset을 바꾼다고 자동으로 셀이 이동하지 않는다.
func adjustContentInset(){
let indexPath = IndexPath(item: 0, section: 0)
if let first = detailCollectionView.cellForItem(at: indexPath){
let topInset = detailCollectionView.frame.height - first.frame.height - view.safeAreaInsets.top - view.safeAreaInsets.bottom - 20
detailCollectionView.contentInset = UIEdgeInsets(top: topInset, left: 0, bottom: 0, right: 0)
detailCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .bottom)
}
}
주의할 점: viewDidLoad()는 컬렉션뷰에 셀이 표시되기 전에 호출된다.
- 따라서 해당 부분에서 adjustContentInset()을 호출하면 실패한다.
- viewDidAppear()에서 호출하면 작동하기는 하나, 어색하게 된다.(이미 컬렉션뷰가 출력된 뒤에 inset이 적용됨)
viewDidLayoutSubviews()
에서 호출하면 된다.
- collectionView가 subview로 배치되고 나서 셀에 접근 가능하기 때문이다.
4. viewDidLayoutSubviews에서 호출
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
adjustContentInset()
}
- 스크롤 할 때마다 스크롤 위치를 파악할 필요가 있다.
- 여기에 맞게 알파 값을 변경한다.
- 스크롤이 되는 뷰들은 모두
UIScrollView
프로토콜을 채택하므로 해당 델리게이트를 구현할 수 있다.
- 파라미터의
UIScrollView
를 그대로 사용하거나 다운캐스팅하면 된다.
- 스크롤 위치는
contentOffset
으로 확인 가능하다.
- 애니메이션 효과가 필요하면
setContentOffset
을 사용하면 된다.
#function, contentOffset.y 출력 결과
- offset 의 0의 위치는 화면의 가장 위쪽이다.
- 초기에 네비게이션바가 있다면 이를 조정하기 위해 scrollViewDidScroll이 호출된다. (-149)
- 위에서 collectionView의 inset을 이동하였으므로 -605로 또 한번 델리게이트가 실행된다.
- 음수인 이유는 원래 collectionView의 위치보다 아래로 이동했기 때문이다.
- 윗방향으로 스크롤하면 양수가 된다.
스크롤 비율에 따라 dimView 알파값 변경
initialOffsetY
는 아까 collectionView 이동 시 최종 위치 y값 저장
extension PlanetDetailViewController: UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(#function, scrollView.contentOffset.y)
let y = scrollView.contentOffset.y
let half = scrollView.bounds.size.height / 2
if y <= initialOffsetY{
dimView.alpha = 0.0
} else if y <= -half{
let progress = (initialOffsetY - y) / (initialOffsetY + half)
dimView.alpha = progress * 0.4
} else {
dimView.alpha = 0.4
}
}
}