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

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)
}

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)

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)
            ])
    }

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
            }
        }
}

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

Did you find this tutorial helpful?



If you have any questions, please feel free to leave a comment below

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments