티스토리 뷰
일반 StickyHeader는 스크롤을 아래로 내렸을 때 위쪽에 윗변이 붙어있는 것 처럼 보이는 화면을 말한다. 하지만 헤더에는 스크롤을 아래로 내렸을 때도 계속 보여야 하는 필수적인 정보가 포함될 수도 있다. StickyHeader 효과를 그대로 가지고 있으면서 특헤더 중 특정 아래 영역을 항상 보이게 하는 autolayout을 만들어보자.
스토리보드로 만들면 만들 때는 쉽지만 유지보수 하기가 어렵기 때문에 스토리보드를 사용하지 않고 모두 코드로 작성해보도록 하겠다. 스토리보드를 사용하지 않고 코드로 화면을 만드는 방법은 아래 글을 참고하면 된다.
먼저 scrollView를 추가한다. autolayout이 중요하기 때문에 constraint 설정 부분을 자세히 봐야 한다. 참고로 모든 view를 추가하는 코드는 viewDidLoad()에 작성한다.
let scrollView = UIScrollView()
scrollView.backgroundColor = .systemBlue
// 1
scrollView.delegate = self
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
// 2
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
- 스크롤을 할 떄마다 헤더의 layout을 바꿔줘야 하기 때문에 delegate를 설정한다.
- 화면에 꽉 차도록 layout을 설정한다.
let contentView = UIView()
contentView.backgroundColor = .systemGreen
contentView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contentView)
// 1
NSLayoutConstraint.activate([
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
- 이렇게 까지만 하면 layout 에러가 발생하지만 밑에서 추가할 다른 view들에 맞게 contentView의 bottomAnchor를 설정할 것이기 때문에 일단 부분적으로 적용시켰다.
// title
let titleLabel = UILabel()
titleLabel.text = "제목"
titleLabel.font = .boldSystemFont(ofSize: 24)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(titleLabel)
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12)
])
// dummy cell
let cell = UIView()
cell.backgroundColor = .systemPink
cell.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(cell)
NSLayoutConstraint.activate([
cell.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 12),
cell.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
cell.widthAnchor.constraint(equalTo: contentView.widthAnchor, constant: -24),
cell.heightAnchor.constraint(equalToConstant: 1000),
// 1
cell.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12)
])
contentView.layoutIfNeeded()
scrollView.contentSize = CGSize(width: view.frame.width, height: contentView.frame.height)
- 스크롤을 할 수 있게 충분히 큰 view를 추가하고 bottom을 설정해서 자동으로 스크롤 범위가 정해질 수 있도록 한다.
// 1
scrollView.contentInset.top = headerHeightMax
let header = UIView()
header.backgroundColor = .systemPurple
header.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(header)
NSLayoutConstraint.activate([
// 2
header.bottomAnchor.constraint(greaterThanOrEqualTo: view.safeAreaLayoutGuide.topAnchor, constant: headerHeightMin),
header.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
header.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
// 3
headerHeightAnchor = header.heightAnchor.constraint(greaterThanOrEqualToConstant: headerHeightMax)
headerHeightAnchor?.isActive = true
headerTopAnchor = header.topAnchor.constraint(greaterThanOrEqualTo: scrollView.topAnchor, constant: -headerHeightMax)
headerTopAnchor?.isActive = true
- header 크기 만큼 inset을 준다.
- 아래쪽 부분이 언제나 화면에 보이게 하기 위해서 bottomAnchor를 설정한다.
- 스크롤 할 때 마다 sticky 효과를 만드려면 height와 top anchor는 delegate함수에서 추가적인 layout이 필요하다. delegate에서 접근하기 쉽게 따로 변수로 빼서 설정한다.
extension MainViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// 1
if scrollView.contentOffset.y < -scrollView.adjustedContentInset.top {
headerHeightAnchor?.constant = -scrollView.contentOffset.y
headerTopAnchor?.constant = scrollView.contentOffset.y
}
}
}
- 스크롤을 내릴 때만 layout을 다시 계산해서 sticky 효과를 만든다.


'Programming > IOS' 카테고리의 다른 글
Core Data (1) (0) | 2021.11.08 |
---|---|
iOS Expert | CALayer Tutorial 원형 게이지 만들기 with CAShapeLayer (0) | 2021.01.06 |
IOS Beginner | AppDelegate SceneDelegate Lifecycle (0) | 2021.01.04 |
IOS Beginner | UILabel size animation with UIView.animate (0) | 2021.01.02 |
iOS Expert | UICollectionView pinterest layout 만들어보기 (1) | 2020.12.31 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Spring
- Java
- ios
- machine learing
- SHADER
- Cocos2d-x
- Git
- OS
- C/C++
- DesignPattern
- C
- 알고리즘
- rxswift
- 자료구조
- swift
- scala
- 드라마
- SwiftUI
- 국내여행
- C++
- 데이터베이스
- SOCKET
- 수학
- JSP
- winsock
- database
- ue4
- game
- 운영체제
- mongoDB
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함