스크롤 코드에 따라 이미지 높이를 동적으로 변경합니다

24249 단어 Swifttableviewtech

실시 요건


스크롤 업데이트에 따라 화면 맨 위에 이미지 높이 설정


Section Header와 table HeaderView 사이에 공백을 유지하면서 스크롤 가능


위로 굴러가면 Section Header가 화면 맨 위에 멈춰요.


전체 완성 이미지



스크롤 업데이트에 따라 화면 맨 위에 이미지 높이 설정


기본적인 처방은 다음과 같다.
  • UItableView를 사용하여 tableHeaderView에서 UIImageView가 있는 Custom View
  • 를 설정합니다.
  • 스크롤할 때마다offset의 값에 따라Custom View가 가지고 있는 UIImageView 밑에 있는 제약과 높이의 제약을 업데이트합니다
  • 소스 코드


    ViewController.swift
    
    import UIKit
    
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
        private lazy var tableView: UITableView = {
            let view = UITableView()
            view.delegate = self
            view.dataSource = self
            view.contentInsetAdjustmentBehavior = .never
            view.register(SectionHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
            view.register(ContentCell.self, forCellReuseIdentifier: "Cell")
            return view
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupTableView()
            makeConstraints()
        }
    
        private func makeConstraints() {
            view.addAutoLayoutedSubview(tableView)
            NSLayoutConstraint.activate(tableView.fillConstraintsWithTopSafeArea())
        }
    
        private func setupTableView() {
            let headerView = StretchyTableHeaderView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: StretchyTableHeaderView.imageHeihgt))
            self.tableView.tableHeaderView = headerView
    
            let view = UIView()
            view.backgroundColor = .orange
            tableView.tableHeaderView?.addAutoLayoutedSubview(view)
            NSLayoutConstraint.activate([
                view.centerXAnchor.constraint(equalTo: tableView.tableHeaderView!.centerXAnchor),
                view.widthAnchor.constraint(equalTo: tableView.tableHeaderView!.widthAnchor),
                view.heightAnchor.constraint(equalToConstant: 30),
                view.topAnchor.constraint(equalTo: tableView.tableHeaderView!.bottomAnchor)
            ])
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? ContentCell else {
                fatalError("Failed To get a CustomCell")
                return UITableViewCell() }
            return cell
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            1
        }
    
        func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            let sectionHeader = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as? SectionHeaderView
            return sectionHeader
        }
    
        func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
            return 50
        }
    
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let headerView = self.tableView.tableHeaderView as! StretchyTableHeaderView
            headerView.scrollViewDidScroll(scrollView: scrollView)
        }
    }
    
    StretchyTableHeaderView.swift
    
    class StretchyTableHeaderView: UIView {
        static let imageHeihgt = 328.3333333333333
        private var imageViewHeight = NSLayoutConstraint()
        private var imageViewBottom = NSLayoutConstraint()
    
        private lazy var imageView: UIImageView = {
            let view = UIImageView(image: UIImage(named: "headerImage"))
            view.backgroundColor = .yellow
            view.contentMode = .scaleAspectFill
            return view
        }()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            setConstraints()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        func setConstraints() {
            self.addAutoLayoutedSubview(imageView)
            imageViewBottom = imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
            imageViewHeight = imageView.heightAnchor.constraint(equalTo: self.heightAnchor)
    
            NSLayoutConstraint.activate([
                imageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
                imageViewBottom,
                imageViewHeight,
            ])
        }
    
        func scrollViewDidScroll(scrollView: UIScrollView) {
            let offsetY = -scrollView.contentOffset.y
            imageView.clipsToBounds = offsetY <= 0
            imageViewBottom.constant = offsetY >= 0 ? 0 : -offsetY/4.7
            imageViewHeight.constant = max(offsetY, 0)
        }
    }
    
    자세한 내용github: https://github.com/yuk1ch1/StretchyHeaderImageViewSample

    보태다


    swift
    + imageViewBottom.constant = offsetY >= 0 ? 0 : -offsetY/4.7
    - imageViewBottom.constant = offsetY >= 0 ? 0 : -offsetY/2
    
    여기 원래는/2 베이스의 제약이 업데이트되었는데, 이후 추가적인 기능을 위해 조정한 결과는 4.7

    추가 대응: SectionHeader와tableHeaderView 사이에 공백 상태를 유지하고 스크롤 & SectionHeader가 화면 위에서 정지


    추가 요건은 다음과 같다.
  • tableHeaderView와SectionHeader 사이에 공간이 있기 때문에 이걸 채우고 싶어요
  • 스크롤 시 테이블헤드뷰와 SectionHeader 사이에 공간이 없는 상태로 이동
  • 화면 상단에 Section Header가 고정되어 있고 Section Header가 더 이상 상향할 수 없음
  • 해결책


    위 코드에 따라 공간을 채우는 UIView를 만들고 addSubview를 Section Header에 추가했습니다

    패하다


    TableView style을 grouped로 만들면 공간이 사라져요
    그냥 위로 굴러가면 Section Header가 화면 위에서 계속 사라져요.

    참고 자료


    https://johncodeos.com/how-to-make-a-stretchy-header-in-ios-using-swift/

    좋은 웹페이지 즐겨찾기