0

I have a UIScrollView that has UIStackView with three objects inside it (label, image and label)

How do I let the scrollview work with the stackview?

As you see in code I added the Label11,image1 and label12 to the stack but I want the stack items to change when scrolling to label21, image2 and label22 and I don't know how!

How can I do that? Here is what I have tried:

Layout

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    // parent scroll
    let ScrollView = UIScrollView()
    ScrollView.frame = CGRectMake(0, 0, self.view.frame.size.width, 667)
    ScrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, 667)
    ScrollView.backgroundColor = UIColor.init(colorLiteralRed: 219, green: 237, blue: 254, alpha: 1)
    ScrollView.pagingEnabled = true

    //label1
    let label11 = UILabel()
    label11.text = "label1"

    // image1
    let image1 = UIImageView()
    image1.frame = CGRectMake(self.view.frame.size.width * 1, 0, self.view.frame.size.width, 200)
    image1.image = UIImage(named: "mother1")

    //label2
    let label12 = UILabel()
    label12.text = "label2"

    //label21
    let label21 = UILabel()
    label21.text = "label1"

    // image2
    let image = UIImageView()
    image.frame = CGRectMake(self.view.frame.size.width * 1, 0, self.view.frame.size.width, 200)
    image.image = UIImage(named: "mother1")

    //label22
    let label22 = UILabel()
    label22.text = "label2"

    //Stackview
    let stackView = UIStackView(arrangedSubviews: [label11, image1, label12])

    stackView.distribution = .FillEqually
    stackView.axis = .Vertical
    stackView.alignment = .Fill
    stackView.spacing = 0
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.backgroundColor = UIColor.blueColor()

    ScrollView.addSubview(stackView)

    let margins = ScrollView.layoutMarginsGuide
    stackView.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor, constant: 0).active = true
    stackView.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor, constant: 0).active = true
    stackView.topAnchor.constraintEqualToAnchor(margins.topAnchor, constant: 0).active = true
    stackView.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor, constant: 0).active = true
    stackView.widthAnchor.constraintEqualToAnchor(ScrollView.widthAnchor, constant: 0).active = true
    stackView.heightAnchor.constraintEqualToAnchor(ScrollView.heightAnchor, constant: 0).active = true

    self.view.addSubview(ScrollView)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}
user3126427
  • 855
  • 2
  • 14
  • 29
  • You need to explain some more what you want to happen and how that is different from what you have now. "the stack items should change when scrolling to label21, image2 and label22" is not clear. – Craig Siemens Apr 11 '16 at 22:11
  • you're right. I clarified by adding the part that I don't know how. thx! – user3126427 Apr 11 '16 at 22:39
  • I had the same issue. I got frustrated to do it dynamically, the way I also prefer. Hope someone explains this uistackview business. – user1019042 Apr 11 '16 at 22:44
  • Possible duplicate of [Is it possible for UIStackView to scroll?](http://stackoverflow.com/questions/31668970/is-it-possible-for-uistackview-to-scroll) – Dalmazio Apr 14 '17 at 09:21

2 Answers2

1

I ended up doing it like this. Attached is a code sample

enter image description here

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let parentView = UIView()
    parentView.backgroundColor = UIColor.blackColor()
    parentView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)

    // parent scroll
    let parentScrollView = UIScrollView()
    parentScrollView.frame = CGRectMake(0, 50, self.view.frame.size.width, self.view.frame.size.height - 100)
    parentScrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height - 100)
    parentScrollView.backgroundColor = UIColor.init(colorLiteralRed: 219, green: 237, blue: 254, alpha: 1)
    parentScrollView.pagingEnabled = true

    // add 1st mother
    let imageView1 = UIImageView()
    imageView1.frame = CGRectMake(self.view.frame.size.width * 0, 0, self.view.frame.size.width, 467)
    imageView1.image = UIImage(named: "mother1")

    // add 2nd mother
    let imageView2 = UIImageView()
    imageView2.frame = CGRectMake(self.view.frame.size.width * 1, 0, self.view.frame.size.width, 467)
    imageView2.image = UIImage(named: "mother2")
//-----------------------------------------------------
    // child scroll
    let childScrollView = UIScrollView()
    childScrollView.frame = CGRectMake(0, 467, self.view.frame.size.width, 0)
    childScrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, 0)
    childScrollView.layer.borderColor = UIColor.blackColor().CGColor
    childScrollView.pagingEnabled = true

    // child 1
    let imageViewChild1 = UIImageView()
    imageViewChild1.frame = CGRectMake(self.view.frame.size.width * 0, 0, self.view.frame.size.width, 200)
    imageViewChild1.image = UIImage(named: "child1-1")
    childScrollView.addSubview(imageViewChild1)
    print("the frame of imageViewChild1 is: \(imageViewChild1.frame)")
    // child2
    let imageViewChild2 = UIImageView()
    imageViewChild2.frame = CGRectMake(self.view.frame.size.width * 1, 0, self.view.frame.size.width, 200)
    imageViewChild2.image = UIImage(named: "child2-1")
    childScrollView.addSubview(imageViewChild2)
    print("the frame of imageViewChild2 is: \(imageViewChild2.frame)")
//-----------------------------------------------------
    // child scroll
    let childScrollView2 = UIScrollView()
    childScrollView2.frame = CGRectMake(468, 467, self.view.frame.size.width, 0)
    childScrollView2.contentSize = CGSizeMake(self.view.frame.size.width * 2, 0)
    childScrollView2.layer.borderColor = UIColor.blackColor().CGColor
    childScrollView2.pagingEnabled = true

    let imageViewChild3 = UIImageView()
    imageViewChild3.frame = CGRectMake(self.view.frame.size.width * 0, 0, self.view.frame.size.width, 200)
    imageViewChild3.image = UIImage(named: "user-1")
    childScrollView2.addSubview(imageViewChild3)
    print("the frame of imageViewChild1 is: \(imageViewChild3.frame)")


    let imageViewChild4 = UIImageView()
    imageViewChild4.frame = CGRectMake(self.view.frame.size.width * 1, 0, self.view.frame.size.width, 200)
    imageViewChild4.image = UIImage(named: "user")
    childScrollView2.addSubview(imageViewChild4)
    print("the frame of imageViewChild4 is: \(imageViewChild4.frame)")

//-----------------------------------------------------
    // add label for the button space
    let buttons = UIView()
    buttons.backgroundColor = UIColor.redColor()


    let motherstackView = UIStackView(arrangedSubviews: [imageView2, imageView1])

    motherstackView.distribution = .FillEqually
    motherstackView.axis = .Horizontal
    motherstackView.alignment = .Fill
    motherstackView.spacing = 0
    motherstackView.translatesAutoresizingMaskIntoConstraints = false

    let ChildstackView = UIStackView(arrangedSubviews: [childScrollView, childScrollView2])

    ChildstackView.distribution = .FillEqually
    ChildstackView.axis = .Horizontal
    ChildstackView.alignment = .Fill
    ChildstackView.spacing = 0
    ChildstackView.translatesAutoresizingMaskIntoConstraints = false

    //Stackview
    let stackView = UIStackView(arrangedSubviews: [motherstackView, ChildstackView, buttons])

    stackView.distribution = .Fill
    stackView.axis = .Vertical
    stackView.alignment = .Fill
    stackView.spacing = 0
    stackView.translatesAutoresizingMaskIntoConstraints = false


    parentScrollView.addSubview(stackView)
    parentView.addSubview(parentScrollView)

    stackView.leadingAnchor.constraintEqualToAnchor(parentScrollView.leadingAnchor, constant: 0).active = true
    stackView.trailingAnchor.constraintEqualToAnchor(parentScrollView.trailingAnchor, constant: 0).active = true
    stackView.topAnchor.constraintEqualToAnchor(parentScrollView.topAnchor, constant: 0).active = true
    stackView.bottomAnchor.constraintEqualToAnchor(parentScrollView.bottomAnchor, constant: 0).active = true
    stackView.widthAnchor.constraintEqualToAnchor(parentScrollView.widthAnchor,multiplier: 2, constant: 0).active = true
    stackView.heightAnchor.constraintEqualToAnchor(parentScrollView.heightAnchor, constant: 0).active = true
    motherstackView.heightAnchor.constraintEqualToAnchor(ChildstackView.heightAnchor, multiplier: 1).active = true
    ChildstackView.heightAnchor.constraintEqualToAnchor(buttons.heightAnchor, multiplier: 2).active = true


    self.view.addSubview(parentView)

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}
user3126427
  • 855
  • 2
  • 14
  • 29
1

For people who needs cocoapods solution try ScrollableStackView library. Here is the github page :

https://github.com/gurhub/ScrollableStackView

Here is some sample codes :

Swift

import ScrollableStackView

var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)

// add your views with 
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...

Objective-C

@import ScrollableStackView

ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];

UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];

// add your views with
[scrollable.stackView addArrangedSubview:rectangle]; 
// ...

Hope it helps someone.

MGY
  • 7,245
  • 5
  • 41
  • 74