user1147171 user1147171 - 1 year ago 80
iOS Question

iOS: Non-bouncing scroll for stack of stackviews with stationary element at the top

I am trying to use Xcode IB to create a scrollable group of 16 stackviews positioned one above the other with a 17th stationary stackview at the top that does not scroll. I want to be able to interact with the scrollable stackviews, so I don't want them to bounce back up immediately after I scroll down.

Any programming required I would do in Swift.

Currently I have:

  • a vertical stackview at the top of the view (
    Overview Stack View
    ) that contains

    • one horizontal stackview at the top of the Overview Stack View as the stationary element (this horizontal stackview contains 2 text fields)

    • a scrollview below that, which contains a UIView that in turn contains 16 horizontal stackviews positioned 50 units apart on the Y axis

I find that if I configure the scrollview with
Bounces Vertically
in the Attributes Inspector, I can scroll the stackviews but they always bounce back up immediately, making them difficult or impossible to interact with. If I don't include
Bounces Vertically
, the group of stackviews doesn't scroll at all.

Github repo here

This image shows the project in XCode:

project in Xcode

I have read a number of questions and answers on Stackoverflow (which is how I got this far) but none of the proposed solutions has helped me solve this.

Any help will be greatly appreciated!

Answer Source

This works for my situation:

  1. Make ViewController a UIScrollView delegate
  2. Create an outlet to the Main ScrollView
  3. Add code based on this answer (I made some changes, plus there were some changes required for XCode 8.1.)

See code for ViewController below (also in github).

Hope this helps someone!

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    @IBOutlet weak var mainScroll: UIScrollView!

    let stackHeight: CGFloat = 30.0

    override func viewDidLoad() {
        mainScroll.delegate = self
        print("----- viewDidLoad -----")
        let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.swiped(_:)))
        swipeDown.direction = UISwipeGestureRecognizerDirection.Down

        let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.swiped(_:)))
        swipeUp.direction = UISwipeGestureRecognizerDirection.Up

    func swiped(gesture: UIGestureRecognizer)
        if let swipeGesture =  gesture as? UISwipeGestureRecognizer
            switch swipeGesture.direction
            case UISwipeGestureRecognizerDirection.Down:
                if (mainScroll.contentOffset.y >= 30) {
                    mainScroll.contentOffset.y = mainScroll.contentOffset.y - 85
            case UISwipeGestureRecognizerDirection.Up:
                print("UP \(mainScroll.contentOffset.y)")
                if (mainScroll.contentOffset.y <= 30*16 ) {
                    mainScroll.contentOffset.y = mainScroll.contentOffset.y+85

    override func didReceiveMemoryWarning() {
        // Dispose of any resources that can be recreated.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download