如何在 UIScrollView 中添加 UIStackView

Posted

技术标签:

【中文标题】如何在 UIScrollView 中添加 UIStackView【英文标题】:How to add UIStackView inside an UIScrollView 【发布时间】:2016-04-11 21:38:09 【问题描述】:

我有一个UIScrollView,它有一个UIStackView,里面有三个对象(标签、图像和标签)

如何让滚动视图与堆栈视图一起使用?

正如您在代码中看到的,我将 Label11、image1 和 label12 添加到堆栈中 但我希望在滚动到 label21、image2 和 label22 时更改堆栈项,但我不知道怎么做!

我该怎么做?这是我尝试过的:

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.


【问题讨论】:

您需要解释更多您想要发生的事情以及这与您现在的情况有何不同。 “滚动到 label21、image2 和 label22 时堆栈项应该改变”不清楚。 你是对的。我通过添加我不知道的部分来澄清。谢谢! 我遇到了同样的问题。我对动态地做这件事感到沮丧,我也喜欢这种方式。希望有人解释这个 uistackview 业务。 Is it possible for UIStackView to scroll?的可能重复 【参考方案1】:

我最终这样做了。附上代码示例

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.




【讨论】:

【参考方案2】:

对于需要 cocoapods 解决方案的人,请尝试 ScrollableStackView 库。这是github页面:

https://github.com/gurhub/ScrollableStackView

这里是一些示例代码:

斯威夫特

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]; 
// ...

希望对某人有所帮助。

【讨论】:

以上是关于如何在 UIScrollView 中添加 UIStackView的主要内容,如果未能解决你的问题,请参考以下文章

如何在 uiscrollview 中添加六个控制器?

如何在 UiScrollview 中获取子视图的内容

如何在像 BBC 新闻应用一样的 UIScrollView 中添加“广告”?

如何将 UIScrollView 添加到基于 xib 的视图中

如何将 UILabel 添加到 UIScrollView?

如何在 UIScrollView 上添加 UIView