3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift】伸縮するTableViewヘッダーを作成する

Last updated at Posted at 2021-08-31

ツイッターのように画面を下にスクロールした際に、画像が拡大するヘッダーを実装する機会があったので備忘録として書きます!

##完成形
TableViewを下に引っ張った際に画像を拡大させる。

currymov

##実装方法
AutoLayoutなど様々なやり方があると思いますが、今回はTableViewCellを使用した方法で実装していきます。

##①カスタムセルを用意する
適当なセルを用意してUIImgeViewをのせます。

StretchyHeaderTableViewCell.swift
import UIKit

final class StretchyHeaderTableViewCell: UITableViewCell {

    @IBOutlet weak var headerImageView: UIImageView!
    static var className: String {
        return String(describing: self)
    }

    static var idetifier: String {
        return className
    }

    static func nib() -> UINib {
        return UINib(nibName: idetifier, bundle: nil)
    }

    func configure(headerImageUrl: String) {
        headerImageView.image = UIImage(named: headerImageUrl)
    }
}

##②TableViewへ登録する
上記で作成したカスタムセルをtableviewへ登録します。
##③制約を加える

StretchyHeaderViewController.swift
private var lastContentOffset = CGPoint.zero
StretchyHeaderViewController.swift
extension StretchyHeaderViewController: UITableViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y <= 0.0 {
            if let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) {
                let deltaY = CGFloat(fabsf(Float(scrollView.contentOffset.y)) - fabsf(Float(lastContentOffset.y)))
                cell.frame = CGRect(x: 0.0, y: scrollView.contentOffset.y, width: cell.frame.size.width, height: cell.frame.size.height + deltaY)
                lastContentOffset = scrollView.contentOffset
            }
        }
    }

##全体のコード

StretchyHeaderViewController.swift

import UIKit

final class StretchyHeaderViewController: UIViewController {
    @IBOutlet private weak var tableView: UITableView!
    private var lastContentOffset = CGPoint.zero
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.tableFooterView = UIView()
        tableView.register(StretchyHeaderTableViewCell.nib(), forCellReuseIdentifier: StretchyHeaderTableViewCell.idetifier)
    }
}
extension StretchyHeaderViewController: UITableViewDelegate {

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if scrollView.contentOffset.y <= 0.0 {
            if let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) {
                let deltaY = CGFloat(fabsf(Float(scrollView.contentOffset.y)) - fabsf(Float(lastContentOffset.y)))
                cell.frame = CGRect(x: 0.0, y: scrollView.contentOffset.y, width: cell.frame.size.width, height: cell.frame.size.height + deltaY)
                lastContentOffset = scrollView.contentOffset
            }
        }
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200
    }
}

extension StretchyHeaderViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: StretchyHeaderTableViewCell.idetifier) as! StretchyHeaderTableViewCell
        cell.configure(headerImageUrl: "curry")
        return cell
    }
}

##最後に
一見難しそうですがたったこれだけでツイッターライクなヘッダーが完成します。最近のアプリだとスクロール時に画像が拡大するものが多いのでぜひ参考にしてください!

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?