Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView max and min contentOffsets?

Given a UIScrollView with any of its standard properties configured (e.g. contentInset), how can I get the minimum and maximum contentOffset?

I.e. when the user scrolls all the way up to the left, what will the contentOffset be reported as?

I.e. if the user were to scroll all the way down to the bottom right, what will the contentOffset be reported as?

like image 849
Senseful Avatar asked May 26 '17 01:05

Senseful


People also ask

How does UIScrollView work?

UIScrollView has a DecelerationRate , which can be either . normal , or . fast , and you can use it to adjust the velocity of scroll deceleration. The documentation states that DecelerationRate determines the rate of scroll deceleration.

What is UIScrollView?

UIScrollView is the superclass of several UIKit classes, including UITableView and UITextView . A scroll view is a view with an origin that's adjustable over the content view. It clips the content to its frame, which generally (but not necessarily) coincides with that of the application's main window.

What is scroll view in iOS?

In iOS, scroll views are used to view content that won't fit entirely on the screen. Scroll views have two main purposes: To let users drag the area of the content they want to display. To let users zoom in to or out of the displayed content using the pinch gestures.


1 Answers

Imagine we have the following UIScrollView:

  • contentSize: 500 x 500
  • frame/bounds size: 200 x 200
  • contentInsets: (10, 10, 20, 20)

Calculated contentOffsets:

  • Min contentOffset:
    • .x: -contentInset.left (-10)
    • .y: -contentInset.top (-10)
  • Max contentOffset
    • .x: contentSize.width - bounds.width + contentInset.right (320)
    • .y: contentSize.height - bounds.height + contentInset.bottom (320)

Normally a UIScrollView starts at contentOffset = (0, 0). However, when you add contentInsets, it starts offset by a negative amount. When you scroll the first position into view so that you don't see the contentInset, you'll be at contentOffset = (0,0).

A similar thing happens at the end, where instead of 300 being the max offset, 320 becomes the max.

func minContentOffset(scrollView: UIScrollView) -> CGPoint {
    return CGPoint(
        x: -scrollView.contentInset.left,
        y: -scrollView.contentInset.top)
}

func maxContentOffset(scrollView: UIScrollView) -> CGPoint {
    return CGPoint(
        x: scrollView.contentSize.width - scrollView.bounds.width + scrollView.contentInset.right,
        y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.contentInset.bottom)
}

You could then create a function that uses both of those to determine if a scroll view is scrollable:

func canVerticallyScroll(scrollView: UIScrollView) -> Bool {
    let scrollableHeight = maxContentOffset(scrollView: scrollView).y
        - minContentOffset(scrollView: scrollView).y
    let viewableHeight = scrollView.bounds.height
    return viewableHeight < scrollableHeight
}

Or as an extension:

extension UIScrollView {

  var minContentOffset: CGPoint {
    return CGPoint(
      x: -contentInset.left,
      y: -contentInset.top)
  }

  var maxContentOffset: CGPoint {
    return CGPoint(
      x: contentSize.width - bounds.width + contentInset.right,
      y: contentSize.height - bounds.height + contentInset.bottom)
  }

  func scrollToMinContentOffset(animated: Bool) {
    setContentOffset(minContentOffset, animated: animated)
  }

  func scrollToMaxContentOffset(animated: Bool) {
    setContentOffset(maxContentOffset, animated: animated)
  }
}
like image 198
Senseful Avatar answered Nov 13 '22 02:11

Senseful