Home > Mobile >  UIScrollView scroll once for users to notice
UIScrollView scroll once for users to notice

Time:09-27

How can I make scrollview scroll to bottom a little bit and scroll to top a little bit again. I has to be animated so users will notice there is a scroll view. I tried this code block but didn't work.

public extension UIScrollView {
   
    func scrollToBottom(animated: Bool) {
        let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height   contentInset.bottom)
        setContentOffset(bottomOffset, animated: animated)
    }
    
    func scrollToTop(animated: Bool) {
        setContentOffset(.zero, animated: animated)
    }
    
    func scrollableAnimation(animated: Bool) {
        scrollToBottom(animated: animated)
        UIView.animate(withDuration: 0.5, delay: 0.5) {
            self.scrollToTop(animated: animated)
        }
    }
} 

CodePudding user response:

You can play with this code and also change the animation accordingly . you can change the x and y value to change the scroll position accordingly

UIView.animate(withDuration: 1.0, delay: 0.3, options: .transitionCurlDown) {
   self.scrollView.setContentOffset(CGPoint(x: 0, y: 200), animated: true)
 } completion: { res in
      self.scrollView.setContentOffset(CGPoint(x: 0, y: -200), animated: true)}

CodePudding user response:

I have reason to believe that your call to get the contentSize.height of the scrollview content returns 0.

Example I have used

I made a VC with a UIScrollView which embeds a UIStackView, which in return has multiple UIViews of various sizes embedded in it.

Heights of each UIViews embedded in the UIStackView are as follows (See the results gif for to better understand):

Yellow: 250
Blue: 1000
LightBlue: 500
Pink: 250

Total: 2000

Solution

To rectify the issue of content height being 0, add a computed property that will get the contentSize after laying out any subviews in the scroll view. Refer to scrollViewContentHeight: CGFloat in the following code:

class ViewController: UIViewController {
    
    // Any IBOutlets

    /// To get the height of the content embedded inside the scrollview
    var scrollViewContentHeight: CGFloat {
        scrollview.layoutIfNeeded()
        return scrollview.contentSize.height
    }
    
    override func viewDidLoad() {...}
    
    override func viewDidAppear(_ animated: Bool) {...}
}

This will return the actual content height (in the case of my example, 2000) of the scrollView. Using this, you can run the animations using the scroll view animations you have provided.

It is important that you trigger the animations in the viewDidAppear(animated:) lifecycle function as that is where animations are usually triggered. And more importantly, that's when the user will first see the view, meaning the content of the entire VC (including the scroll view) would have already been loaded.

Results

Here I have added a print() statement inside the viewDidAppear(animated:) function to verify the content height of the scroll view:

enter image description here

Finally, the results of the experiment can be seen in the gif below, followed by the code:

enter image description here

class ViewController: UIViewController {

    @IBOutlet weak var scrollview: UIScrollView!
    
    /// Height of the content embedded inside the scrollview
    var scrollViewContentHeight: CGFloat {
        scrollview.layoutIfNeeded()
        return scrollview.contentSize.height
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        print("The scrollView height is:",scrollViewContentHeight)

        // Begin scroll to bottom animation
        DispatchQueue.main.asyncAfter(deadline: .now()   1, execute: {
            self.scrollview.scrollToBottom(animated: true)
        })
        
        // Begin scroll to top animation
        DispatchQueue.main.asyncAfter(deadline: .now()   2, execute: {
            self.scrollview.scrollToTop(animated: true)
        })
    }
}
  • Related