I want to slide my table view header into view if the use scrolls up my feed and the header is off screen. If the user then scrolls down I want to hide it again.
I believe I have this working using the following:
final class AccountSettingsController: UITableViewController {
let items: [Int] = Array(0...500)
private lazy var menuView: UIView = {
let view = UIView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .systemPink
view.heightAnchor.constraint(equalToConstant: 120).isActive = true
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = []
extendedLayoutIncludesOpaqueBars = false
tableView.tableHeaderViewWithAutolayout = menuView
tableView.tableFooterView = .init()
tableView.refreshControl = .init()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "This is setting #\(indexPath.row)"
return cell
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset.y
let transY = scrollView.panGestureRecognizer.translation(in: scrollView).y
if scrollView.contentOffset.y > 120 {
if transY > 0 {
menuView.transform = .init(translationX: 0, y: contentOffset)
} else if transY < 0 {
menuView.transform = .identity
}
return
}
if scrollView.contentOffset.y <= 120 {
if transY < 0 {
menuView.transform = .identity
} else if transY > 0 {
menuView.transform = .init(translationX: 0, y: contentOffset)
}
}
}
}
I would like to animate the slide in / slide out of the header, so it slides down and up, rather than just appears.
I tried to add UIView.animate blocks such as
if scrollView.contentOffset.y <= 120 {
if transY < 0 {
menuView.transform = .identity
} else if transY > 0 {
UIView.animate(withDuration: 0.25, animations: {
self.menuView.transform = .init(translationX: 0, y: contentOffset)
})
}
}
but this produces a random jumping effect on the header and does not achieve what I would like at all.
I've attached a gif that shows the current effect, as you can see it just appears and disappears. I'd like this to animate down and up for for show / hide.
I also have an extension to set the correct size for my table view header, which you can find here -
extension UITableView {
var tableHeaderViewWithAutolayout: UIView? {
set (view) {
tableHeaderView = view
if let view = view {
lowerPriorities(view)
view.frame.size = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
tableHeaderView = view
}
}
get {
return tableHeaderView
}
}
fileprivate func lowerPriorities(_ view: UIView) {
for cons in view.constraints {
if cons.priority.rawValue == 1000 {
cons.priority = UILayoutPriority(rawValue: 999)
}
for v in view.subviews {
lowerPriorities(v)
}
}
}
}
