How to add Scroll To Top in TableView and CollectionView in iOS using Swift

In this tutorial, we are going to cover how to implement scroll to the top to your UITableView and UICollectionView easily.

Scroll to the top is a way to help the user to go at the top of the list fast without the need to scroll manually.

You can do that by making the pressing UINavigationBar‘s Title or with a button that pops up when we start to scroll down.

Add Scroll To Top in Navigation Bar Title for UITableView/UICollectionView

To make the title of UINavigationBar recognize our tap, we need to replace the already existed title, that UINavigationBar has, with a UILabel that recognizes tap gesture to scroll to the top when we are pressing it:

func TapLabelToScrollToTheTop(font: UIFont, textColor: UIColor, backgroundColor: UIColor) { let titlelabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40)) titlelabel.text = self.navigationItem.title titlelabel.textColor = textColor titlelabel.font = font titlelabel.backgroundColor = backgroundColor titlelabel.textAlignment = .center let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.labelTapped)) tapGestureRecognizer.numberOfTapsRequired = 1 titlelabel.addGestureRecognizer(tapGestureRecognizer) titlelabel.isUserInteractionEnabled = true self.navigationItem.titleView = titlelabel } @objc func labelTapped(_ sender: UITapGestureRecognizer) { //Press the navigation label to go at the top let topOffest = CGPoint(x: 0, y: -(self.tableView?.contentInset.top ?? 0)) self.tableView?.setContentOffset(topOffest, animated: true) }
Code language: Swift (swift)

After that, we call the method in viewDidLoad() or viewWillAppear() and always after self.title like this:

self.title = "Title" TapLabelToScrollToTheTop(font: UIFont.systemFont(ofSize: 17, weight: .semibold), textColor: UIColor.white, backgroundColor: UIColor.clear)
Code language: Swift (swift)

Note: If the title doesn’t appear, use self.navigationController?.navigationBar.topItem?.title = "Title" instead of self.title="Title"

Add Scroll To The Top in Button for UITableView/UICollectionView

This method is very common when you create a chat. The user scrolls to see their chat history and a button with an arrow appears to scroll back to the conversation.

First, we create the UIView and UIImageView, that contains the arrow, programmatically with the UITapGestureRecognizer and the auto layout constraints:

var arrowView = UIView(frame: CGRect.zero) let arrowImgView = UIImageView(frame: CGRect.zero) override func viewDidLoad() { super.viewDidLoad() //ArrowView arrowView.layer.cornerRadius = 25 arrowView.backgroundColor = UIColor.black arrowView.layer.borderWidth = 1.5 arrowView.layer.borderColor = UIColor.white.cgColor self.view.addSubview(arrowView) arrowImgView.image = UIImage(cgImage: UIImage(named: "back-arrow")!.cgImage!, scale: CGFloat(1.0), orientation: .right) arrowImgView.image = arrowImgView.image!.withRenderingMode(.alwaysTemplate) arrowImgView.tintColor = UIColor.white let TapScrollDown = UITapGestureRecognizer(target: self, action: #selector(ScrollToTheTop(_:))) arrowImgView.isUserInteractionEnabled = true arrowImgView.addGestureRecognizer(TapScrollDown) arrowView.addSubview(arrowImgView) SetArrowAutoLayouts() } @objc func ScrollToTheTop(_ sender: UITapGestureRecognizer) { let topOffest = CGPoint(x: 0, y: -(self.tableView?.contentInset.top)) self.tableView.setContentOffset(topOffest, animated: true) } @objc func SetArrowAutoLayouts() { arrowView.translatesAutoresizingMaskIntoConstraints = false arrowViewWidth = arrowView.widthAnchor.constraint(equalToConstant: 50) arrowViewHeight = arrowView.heightAnchor.constraint(equalToConstant: 50) arrowViewBottom = arrowView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -50) arrowViewRight = arrowView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 55) arrowViewWidth.isActive = true arrowViewHeight.isActive = true arrowViewBottom.isActive = true arrowViewRight.isActive = true arrowImgView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ arrowImgView.topAnchor.constraint(equalTo: arrowView.topAnchor, constant: 8), arrowImgView.leadingAnchor.constraint(equalTo: arrowView.leadingAnchor, constant: 8), arrowImgView.bottomAnchor.constraint(equalTo: arrowView.bottomAnchor, constant: -8), arrowImgView.trailingAnchor.constraint(equalTo: arrowView.trailingAnchor, constant: -8) ]) }
Code language: Swift (swift)

Next, we’re going to add to our UITableView/UICollectionView the scrollViewDidScroll method.

This method detects the X and Y position of the UIScrollView that UITableView/UICollectionView has. We’re gonna use this to detect when the user starts to scrolls down:

var scrollTop = true func scrollViewDidScroll(_ scrollView: UIScrollView) { let offsetY = scrollView.contentOffset.y if offsetY > 400 { if scrollTop { arrowViewRight.constant = -12 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } scrollTop = false } }else{ if !scrollTop { arrowViewRight.constant = 55 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } scrollTop = true } } }
Code language: Swift (swift)

If you want to show the button as soon as the user scrolls down, change the value from 400 to something smaller. The smaller the value, the sooner the Scroll To Top arrow will appear.

And that’s it! Done!

You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Get once a week my latest tutorials right in your inbox

Check your inbox to confirm your email