Custom UIScrollView Indicator

How to create a custom scroll view indicator for UIScrollview?

Hi all, in this article, I am going to explain how to create a custom scroll view indicator with the help of UIProgressView. Custom indicators can be used as a proactive visual element that indicates to the user how much they have scrolled. In our use case, a custom scroll view is used to show users how much they have read an article (or scrolled through it).

UIProgressView (a.k.a Progress View) provides a progress bar that shows the progress of a task over time. We can update the view by updating its progress property. By default, the progress should be between 0.0 to 1.0 where 0 means no progress is done and 1 means the task has been completed.

To use Progress View we need to calculate how much scrolling is done i.e. how much progress the user has made in the scrolling task. And then we have to normalize its value between 0 to 1. The normalized progress can be calculated by dividing the current offset by the maximum possible offset. The offset represents the distance by which the scroll view has been scrolled. We also need to consider the minimum possible offset while calculating. So, the final formula to calculate the progress will look something like this:

$$ progress = (current‎‎‎‎ offset - minimum offset) / (maximum offset - minimum offset) $$

We can get the current offset of a scroll view by its contentOffset property at any point. Ideally the offset should start from 0, but if there is some contentInset present in the scroll view then the offset will start from that inset. So the minimum offset will be negative of contentInset. Similarly, We have to add the contentInset to the (complete scrollable) height of the scroll view to calculate the maximum offset. But we also need to remove the height of the scroll view bounds (i.e. bounds which are visible on the screen) because it can be assumed that the user has already scrolled that much height.

We can squeeze all the calculations to calculate progress inside an extension of UIScrollView in swift.

extension UIScrollView {
  var minimumContentOffset: CGFloat { -contentInset.top }

  var maximumContentOffset: CGFloat {
    return contentSize.height - (bounds.size.height - contentInset.bottom)
  }

  var progress: CGFloat {
    return (contentOffset.y - minimumContentOffset) / (maximumContentOffset - minimumContentOffset)
  }
}

Now to update the progress whenever the scrolling is done we can use the scrollviewDidScroll delegate call.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
  progressView.progress = Float(scrollView.progress)
}

Finally, the result should look something like this:

Thanks for reading!


Some references to follow for more information: