27

I would like to set the contentOffset of my scrollview programmatically when the contentOffset is between two points (please see the picture below) with Swift.

The problem is, I would like to add a smooth transition for the move, but I didn't find documentation for this. I tried to do a loop in order to decrease gradually the content offset but the result is not so good.

With this example, if the content offset is less than 150 px at the end of the scroll, it goes smoothly (duration of the animation would be 1 sec) to the point with the offset equal to 100. Up to 150 px, it goes to 200px.

If you can provide me directions (documentation or quick example) of what to do it would be great :) Thank you !

enter image description here

Jibeee
  • 822
  • 1
  • 11
  • 26

4 Answers4

44

You can use UIView.animations

  func goToPoint() {
    dispatch_async(dispatch_get_main_queue()) {
      UIView.animateWithDuration(2, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: {
        self.scrollView.contentOffset.x = 200
        }, completion: nil)
    }
  }

Swift version

DispatchQueue.main.async {
    UIView.animate(withDuration: 0.2, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
        self.myScrollView.contentOffset.x = CGFloat(startingPointForView)
    }, completion: nil)
}

Swift 4

DispatchQueue.main.async {
    UIView.animate(withDuration: 1, delay: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.scrollView.contentOffset.x = 200
    }, completion: nil)
}
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
  • Thank you very much, I used your code to make Swift 3 version. edit - I'll post it as an answer to this because the code gets messy in here. – Darko Oct 03 '16 at 15:54
  • 2
    @fatihyildizhan So used this code and works like I charm, thanks! I tried to make the same but not in `dispatch_async(dispatch_get_main_queue())` and it didn't work properly because during animation contentOffset is setting back to 0.0. Could you explain me why we need this make in `dispatch_async(dispatch_get_main_queue())` to work properly? – Mette Nov 21 '16 at 19:13
10

Here is the Swift 3 version of fatihyildizhan's code.

DispatchQueue.main.async {
    UIView.animate(withDuration: 0.2, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
        self.myScrollView.contentOffset.x = CGFloat(startingPointForView)
    }, completion: nil)
}
Mohamed Salah
  • 868
  • 1
  • 15
  • 34
Darko
  • 615
  • 7
  • 21
9

Now you can simply call the method setContentOffset(_ contentOffset: CGPoint, animated: Bool) instead of the previous workarounds calling a messy animation block. See:

x = CGFloat(startingPointForView)
myScrollView.setContentOffset(CGPoint(x: x, y: 0), animated: true)

Hope it helps.

thorng
  • 93
  • 1
  • 4
3

Swift 4:

DispatchQueue.main.async {
    UIView.animate(withDuration: 1, delay: 0, options: UIView.AnimationOptions.curveLinear, animations: {
            self.scrollView.contentOffset.x = 200
    }, completion: nil)
}
Charlie S
  • 4,366
  • 6
  • 59
  • 97