Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- collectionview
- rxswift
- Observable
- UITextView
- swiftUI
- tableView
- 스위프트
- MVVM
- Protocol
- 클린 코드
- Xcode
- Refactoring
- uiscrollview
- ios
- SWIFT
- 애니메이션
- Human interface guide
- 리팩토링
- uitableview
- Clean Code
- map
- ribs
- 리펙터링
- swift documentation
- RxCocoa
- 리펙토링
- UICollectionView
- HIG
- clean architecture
- combine
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] UIScrollView in UIScrollView (nested scrollView 스크롤 제어 방법, scrollViewDidScroll, contentOffset) 본문
UI 컴포넌트 (swift)
[iOS - swift] UIScrollView in UIScrollView (nested scrollView 스크롤 제어 방법, scrollViewDidScroll, contentOffset)
jake-kim 2023. 1. 10. 22:32
nested scrollView
- 안쪽과 바깥쪽 스크롤 뷰 모두 isScrollEnabled가 on인 경우, 아래처럼 안쪽 스크롤이 활성화되어 있는 상태
- 단, 안쪽 스크롤이 상단까지 스크롤된 경우, 더 이상 스크롤 할 내용이 없다면 아래처럼 자동으로 바깥쪽 스크롤이 되는 형태
- 스크롤 뷰 안에 또다른 스크롤 뷰가 있을 경우, 바깥쪽 스크롤이 어느정도 스크롤 되었을 때 안쪽 스크롤 뷰가 스크롤 되도록 하는 방법?
- 1) 안쪽 스크롤의 isScrollEnabled를 false로 초기화
- 2) scrollViewDidScroll()델리게이스 메소드에서 contentOffset을 보고 스크롤을 상단 뷰의 길이만큼 한 경우 스크롤 활성화
구현 방법
* 예제에는 코드로 오토레이아웃 정의에 편리한 SnapKit 사용
- ViewController 준비
- 바깥쪽 scrollView, 안쪽 tableView
- tableView위에 emptyView가 존재
- tableView의 isScorllEnabled = false로 설정 (안쪽 스크롤뷰가 스크롤 안되고 바깥쪽 스크롤이 되도록 설정)
- bounces가 true이면 스크롤을 막아도 스크롤이 바운스되며 순간적으로 더 스크롤을 할 수 있으므로 비활성화 (bounces = false)
class ViewController: UIViewController {
private let scrollView: UIScrollView = {
let view = UIScrollView()
view.bounces = false
view.backgroundColor = .lightGray.withAlphaComponent(0.2)
return view
}()
private let emptyView = UIView()
private let stackView: UIStackView = {
let view = UIStackView()
view.axis = .vertical
return view
}()
private let tableView: UITableView = {
let view = UITableView()
view.bounces = false
view.backgroundColor = .lightGray
// 1.
view.isScrollEnabled = false
return view
}()
}
- 테이블뷰에 사용할 데이터소스 선언
private let items = (0...500).map(String.init)
- 레이아웃과 테이블뷰 데이터소스 구현
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
scrollView.addSubview(stackView)
stackView.addArrangedSubview(emptyView)
stackView.addArrangedSubview(tableView)
scrollView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
stackView.snp.makeConstraints {
$0.edges.width.equalToSuperview()
}
emptyView.snp.makeConstraints {
$0.height.equalTo(500)
}
tableView.snp.makeConstraints {
$0.height.equalTo(1200)
}
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.dataSource = self
scrollView.delegate = self
tableView.delegate = self
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
}
- scrollViewDidScroll에서 상단 뷰 (emptyView)의 길이에 가깝게 스크롤 된 경우, 안쪽 스크롤 뷰(tableView)의 스크롤을 활성화 시키도록 구현
extension ViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(scrollView.contentOffset.y)
let topMargin = 56.0 // 상단 56.0 마진
let topSpacing = emptyView.bounds.height - topMargin
if scrollView == self.scrollView {
// 상단 뷰의 height만큼 스크롤 한 경우, tableView의 스크롤 on
let shouldOnScroll = topSpacing - scrollView.contentOffset.y < 0
tableView.isScrollEnabled = shouldOnScroll
}
}
}
- scrollView의 contentSize, contentOffset을 사용하여 현재 스크롤이 바닥에 닿았는지 확인이 가능하므로 이것을 사용
extension ViewController: UITableViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.scrollView {
let remainingScrollHeight = scrollView.contentSize.height - scrollView.frame.size.height
let isBottomReached = scrollView.contentOffset.y >= remainingScrollHeight
tableView.isScrollEnabled = isBottomReached
}
}
}
'UI 컴포넌트 (swift)' 카테고리의 다른 글
[iOS - swift] 1. 상단 탭과 하단 수평 스크롤 UI 구현 방법 - 상단 TabHeaderView 구현 (UICollectionView) (0) | 2023.01.16 |
---|---|
[iOS - swift] 2. Sticky Header 구현 - 스크롤 시 상단에 뷰 붙이는 방법 (0) | 2023.01.11 |
[iOS - swift] Custom TabBar 구현 방법 (커스텀 탭바, UIStackView, fillEqually) (0) | 2023.01.08 |
[iOS - swift] 1. Sticky Header 구현 - 스크롤 시 상단 해더 숨기는 방법 (0) | 2023.01.07 |
[iOS - swift] Custom Button 만드는 방법 (커스텀 버튼) (1) | 2023.01.04 |
Comments