Programmatic UIScrollview with Autolayout
You don't need to create a faux content view, you can add subviews directly to the scroll view (which I prefer). Apple does not recommend creating one, they only suggest that you can.
Subviews of the scroll view shall not rely on the scroll view to determine their sizes, only their positions.
Your constraints must define the left-most, right-most, top-most, and bottom-most edges in order for auto layout to create the content view for you.
When you create a scroll view, you may give its frame the bounds of the controller's view:
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
You must then set the boundaries of the content view by anchoring its subviews to the edges of the scroll view. To achieve vertical-only scrolling, your top-most view must be anchored to the top of the scroll view and none of the subviews anchored to the leading and trailing edges must exceed the width of the scroll view.
topMostView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(topMostView)
topMostView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
topMostView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
topMostView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
topMostView.heightAnchor.constraint(equalToConstant: 1000).isActive = true
Notice the topMostView
does not rely on the scroll view to determine its size, only its position. The content in your scroll view now has a height of 1000
but it won't scroll because nothing is anchored to the bottom of the scroll view. Therefore, do that in your bottom-most view.
bottomMostView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(bottomMostView)
bottomMostView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
bottomMostView.topAnchor.constraint(equalTo: topMostView.bottomAnchor).isActive = true
bottomMostView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
bottomMostView.heightAnchor.constraint(equalToConstant: 1000).isActive = true
bottomMostView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
The last anchor may seem odd because you're anchoring a view that is 1,000
points tall to an anchor that you just anchored to the bottom of the view which is definitely less than 1,000
points tall. But this is how Apple wants you to do it. By doing this, you do not need to create a content view, auto layout does it for you.
Defining the "edge constraints" (left-most, right-most, top-most, bottom-most) goes beyond scroll views. When you create a custom UITableViewCell
, for example, using auto layout, defining the four edge constraints (i.e. where the top-most subview is anchored to the top of the cell topMostView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
, the bottom-most subview to the bottom of the cell bottomMostView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
, etc.) is how you create self-sizing cells. Defining the edge constraints is how you create any self-sizing view, really.
UIScrollView setup with AutoLayout Programmatically
You don't need either of these lines - remove them:
self.containerView.heightAnchor.constraint(equalTo: self.scrollView.frameLayoutGuide.heightAnchor).isActive = true
self.containerView.heightAnchor.constraint(equalTo: self.scrollView.frameLayoutGuide.heightAnchor).priority = .defaultLow
You have no constraint controlling the height of contentView
... you need to add:
// quizOptionsTableView bottom to contentView bottom with 8-points "padding
self.quizOptionsTableView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8).isActive = true
Couple of suggestions...
- Respect the Safe Area
- Stick with
.leadingAnchor
and.trailingAnchor
(right now you're mixing in left/right). - Group actions together ... that is, do your subview adding in one place, your constraints all together ... your UI element properties all together.
- Give your UI elements contrasting background colors to make it easy to see the frames.
Very STRONGLY Recommend: use comments!!!!
Take a look at the way I've edited your code:
class SampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let scrollView = UIScrollView()
let titleLabel = UILabel()
let containerView = UIView()
let contentView = UIView()
let questionImageView = UIImageView()
let questionTitleLabel = UILabel()
let questionNumberLabel = UILabel()
let marksLabel = UILabel()
let quizOptionsTableView = UITableView()
let instructionStackView = UIStackView()
let clockImageView = UIImageView()
let timerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
[scrollView, containerView, contentView, titleLabel, instructionStackView,
questionImageView, questionTitleLabel, questionNumberLabel,
marksLabel, quizOptionsTableView].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
}
//self.scrollView.showsVerticalScrollIndicator = false
self.view.addSubview(self.scrollView)
self.scrollView.addSubview(self.containerView)
self.containerView.addSubview(self.titleLabel)
self.containerView.addSubview(self.instructionStackView)
self.containerView.addSubview(self.contentView)
self.contentView.addSubview(self.questionImageView)
self.contentView.addSubview(self.questionTitleLabel)
self.contentView.addSubview(self.quizOptionsTableView)
self.questionTitleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
let verticalStackView = UIStackView(frame: .zero)
verticalStackView.axis = .vertical
verticalStackView.addArrangedSubview(self.questionNumberLabel)
verticalStackView.addArrangedSubview(self.marksLabel)
self.questionNumberLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
let emptyView = UIView(frame: .zero)
emptyView.widthAnchor.constraint(equalToConstant: 40).isActive = true
let horizantalStackView = UIStackView(frame: .zero)
horizantalStackView.axis = .horizontal
horizantalStackView.addArrangedSubview(emptyView)
horizantalStackView.addArrangedSubview(self.clockImageView)
horizantalStackView.addArrangedSubview(self.timerLabel)
horizantalStackView.spacing = 8
self.instructionStackView.addArrangedSubview(verticalStackView)
self.instructionStackView.addArrangedSubview(horizantalStackView)
let safeGuide = view.safeAreaLayoutGuide
let layoutGuide = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// all 4 sides of scrollView to view
self.scrollView.topAnchor.constraint(equalTo: safeGuide.topAnchor),
self.scrollView.leftAnchor.constraint(equalTo: safeGuide.leftAnchor),
self.scrollView.rightAnchor.constraint(equalTo: safeGuide.rightAnchor),
self.scrollView.bottomAnchor.constraint(equalTo: safeGuide.bottomAnchor),
// all 4 sides of containerView to scrollView's Content Layout Guide
self.containerView.topAnchor.constraint(equalTo: layoutGuide.topAnchor),
self.containerView.leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor),
self.containerView.trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor),
self.containerView.bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor),
// containerView Width to scrollView's Frame Layout Guide
self.containerView.widthAnchor.constraint(equalTo: self.scrollView.frameLayoutGuide.widthAnchor),
// NO height constraint for containerView
// titleLabel to top of containerView + 16-points "padding"
self.titleLabel.topAnchor.constraint(equalTo: self.containerView.topAnchor, constant: 16),
// titleLabel to leading/trailing of containerView
self.titleLabel.leadingAnchor.constraint(equalTo: self.containerView.leadingAnchor),
self.titleLabel.trailingAnchor.constraint(equalTo: self.containerView.trailingAnchor),
// instructionStackView top to titleLabel bottom with 24-points "padding"
self.instructionStackView.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 24),
// instructionStackView to leading/trailing of containerView with 50-points "padding"
self.instructionStackView.leadingAnchor.constraint(equalTo: self.containerView.leadingAnchor, constant: 50),
self.instructionStackView.trailingAnchor.constraint(equalTo: self.containerView.trailingAnchor, constant: -50),
// clockImageView width and height
self.clockImageView.widthAnchor.constraint(equalToConstant: 46),
self.clockImageView.heightAnchor.constraint(equalToConstant: 46),
// contentView top to instructionStackView bottom + 16-points "padding"
self.contentView.topAnchor.constraint(equalTo: self.instructionStackView.bottomAnchor, constant: 16),
// contentView to leading/trailing of containerView with 50-points "padding"
self.contentView.leadingAnchor.constraint(equalTo: self.containerView.leadingAnchor, constant: 50),
self.contentView.trailingAnchor.constraint(equalTo: self.containerView.trailingAnchor, constant: -50),
// contentView bottom to containerView bottom with 16-points "padding"
self.contentView.bottomAnchor.constraint(equalTo: self.containerView.bottomAnchor, constant: -16),
// questionImageView top/leading/trailing to contentView with 8-points "padding"
self.questionImageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8),
self.questionImageView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
self.questionImageView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -8),
// questionImageView height constant
self.questionImageView.heightAnchor.constraint(equalToConstant: 170),
// questionTitleLabel top to questionImageView bottom + 8-points "padding"
self.questionTitleLabel.topAnchor.constraint(equalTo: self.self.questionImageView.bottomAnchor, constant: 8),
// questionTitleLabel leading/trailing to contentView with 8-points "padding"
self.questionTitleLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
self.questionTitleLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -8),
// quizOptionsTableView top to questionTitleLabel + 8-points "padding
self.quizOptionsTableView.topAnchor.constraint(equalTo: self.questionTitleLabel.bottomAnchor, constant: 8),
// quizOptionsTableView leading/trailing to contentView with 8-points "padding"
self.quizOptionsTableView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
self.quizOptionsTableView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -8),
// quizOptionsTableView height constant
self.quizOptionsTableView.heightAnchor.constraint(equalToConstant: 320),
// quizOptionsTableView bottom to contentView bottom with 8-points "padding
self.quizOptionsTableView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -8),
])
// UI element properties
titleLabel.numberOfLines = 0
titleLabel.textAlignment = .center
titleLabel.text = "This is the text for the Title Label which should be able to wrap onto multiple lines."
questionTitleLabel.numberOfLines = 0
questionTitleLabel.text = "This is the text for the Question Title Label which should be able to wrap onto multiple lines just like the Title Label."
questionNumberLabel.text = "1"
marksLabel.text = "Marks?"
if let img = UIImage(systemName: "clock.fill") {
clockImageView.image = img
}
if let img = UIImage(systemName: "photo.tv") {
questionImageView.image = img
}
quizOptionsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "c")
quizOptionsTableView.dataSource = self
quizOptionsTableView.delegate = self
// let's give our UI elements some constrasting colors so we can see their frames
view.backgroundColor = .lightGray
scrollView.backgroundColor = .red
containerView.backgroundColor = .systemGreen
contentView.backgroundColor = .systemBlue
titleLabel.backgroundColor = .yellow
questionTitleLabel.backgroundColor = .cyan
marksLabel.backgroundColor = .green
clockImageView.backgroundColor = .systemYellow
questionImageView.backgroundColor = .systemYellow
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath)
c.textLabel?.text = "\(indexPath)"
return c
}
}
Programmatically layed out UIScrollView, and added auto layout to it's subviews, but it does not scroll
When using Autolayout in UIScrollViews you have to pin subviews both to the top and bottom of the scrollview which allows the scrollview to calculate its contentSize.
Adding this line fixes it:
view4.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
Using AutoLayout and UIScrollView programmatically
The only way I was able to make it work was by adding BottomAnchor to the last UIView inside ContentView. I created a GitHub repo with demo code here
My Swift 4 UIScrollView with autolayout constraints is not scrolling
You can do this with Auto Layout. The secret is to constrain the edges of the containerView
to the edges of the scrollView
. It's not intuitive, but constraining the edges of the containerView
doesn't set the size, it just makes sure that the content size of the scrollView
grows as the containerView
grows. By setting constraints for the width of the containerView
to a constant that is a larger number than the width of the scrollView
, the content will scroll horizontally.
Note: When configuring a scrollView
this way, you do not set the contentSize
of the scrollView
. The contentSize
will be computed for you by Auto Layout and it will be equal to the size of the containerView
. It is important to make sure that the size of the containerView
is fully specified by the constraints.
Here's what I changed to make it work:
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
//containerView.frame = CGRect(x: 0, y: 0, width: 1080, height: 200)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.topAnchor.constraint(equalTo:scrollView.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo:scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo:scrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo:scrollView.bottomAnchor).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 200).isActive = true
containerView.widthAnchor.constraint(equalToConstant: 1080).isActive = true
Why isn't my content scrolling?
For it to scroll, the containerView
must be larger than the scrollView
. Your error is that you have set the constraints such that the containerView
is the same width and height as the scrollView
, and that is why your content isn't scrolling.
If you want it to scroll horizontally, the width of the containerView
must be larger than the scrollView
's width. You can do this in one of two ways:
Specify an explicit constant width for the
containerView
that is larger than thescrollView
's width.OR
Chain the subviews of the
containerView
from left to right with the left most being constained to the leading edge of thecontainerView
. Fully specify the widths of the subviews, and place distance contraints between the subviews. The rightmost subview must have an offset from the trailing edge of thecontainerView
. By doing this, Auto Layout can compute the width of thecontainerView
and set thecontentSize
of thescrollView
.
Mini project: update
This is a version of your mini project which uses a chain of constrained views to define the containerView
's width. The key is the final constraint after the for
loop in viewDidLoad()
which connects the last button's trailingAnchor (aka startPoint
) to the containerView
's trailingAnchor. This completes the chain of contraints and buttons which connect the leading edge of the containerView
with the trailing edge of containerView
. With this, Auto Layout is able to compute the width of the containerView
and establish the contentSize
of the scrollView
.
import UIKit
import PlaygroundSupport
class FilterViewController: UIViewController {
var filterView: UIView!
var scrollView: UIScrollView!
var containerView: UIView!
override func loadView() {
filterView = UIView()
view = filterView
view.backgroundColor = #colorLiteral(red: 0.909803926944733, green: 0.47843137383461, blue: 0.643137276172638, alpha: 1.0)
scrollView = UIScrollView()
scrollView.backgroundColor = #colorLiteral(red: 0.474509805440903, green: 0.839215695858002, blue: 0.976470589637756, alpha: 1.0)
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.25).isActive = true
scrollView.isScrollEnabled = true
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
// This is key: connect all four edges of the containerView to
// to the edges of the scrollView
containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// Making containerView and scrollView the same height means the
// content will not scroll vertically
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
}
class Buttons {
let button = UIButton()
init(titleText: String) {
button.backgroundColor = #colorLiteral(red: 0.976470589637756, green: 0.850980401039124, blue: 0.549019634723663, alpha: 1.0)
button.setTitle(titleText, for: .normal)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let b1 = Buttons(titleText: "one")
let b2 = Buttons(titleText: "two")
let b3 = Buttons(titleText: "three")
let b4 = Buttons(titleText: "four")
let b5 = Buttons(titleText: "five")
let buttonArray = [b1, b2, b3, b4, b5]
var startPoint = containerView.leadingAnchor
for btn in buttonArray {
let theBtn = btn.button
containerView.addSubview(theBtn)
theBtn.translatesAutoresizingMaskIntoConstraints = false
theBtn.leadingAnchor.constraint(equalTo: startPoint, constant: 20).isActive = true
theBtn.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
theBtn.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
theBtn.widthAnchor.constraint(equalTo: theBtn.heightAnchor).isActive = true
startPoint = theBtn.trailingAnchor
}
// Complete the chain of constraints
containerView.trailingAnchor.constraint(equalTo: startPoint, constant: 20).isActive = true
}
}
let filterViewController = FilterViewController()
PlaygroundPage.current.liveView = filterViewController
How to set subviews with AutoLayout in UIScrollView programmatically?
Here is a SO answer has explained how to do this with auto layout, he has explain perfectly , In here there is vertically textfields are there But in your case it is you have to set Horizontal views constraints.
Alternative
Rather that setting constraints you can set just frame of the subview and set it in Scrollview, And based on orientation you can change frames of the scrolview's subviews.
Your setData Method like,
-(void)setData{
[self layoutIfNeeded];
CGRect mainFrame=scrollView.frame;
CGRect frame;
for (int i=0; i<arrayData.count ; i++)
{
CGRect frame;
frame.origin.x = scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
frame.origin=CGPointMake(0, 0);
UIView *subview = [[UIView alloc]initWithFrame:frame];
subview.backgroundColor = [self getRandomColor];
[scrollView addSubview:subview];
}
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * arrayData.count, mainFrame.size.height/2);
}
Now you using NSNotificationCenter you can get notify when device orientation chaged, so in this selector method of it call your setData
method,
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setData)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Now in you setData method you need remove all subviews because when device changes Orientation it will add new views to your scrollview, so remove all subview from Scrollview before setting its frame,
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
Make sure you are removing observer from your class like,
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Programmatic use UIStackView in UIScrollview with Autolayout
The key to getting scroll views to work with auto-layout is to make sure you have a complete "chain" of vertical constraints and element heights, and horizontal constraints and element widths.
Here is an example of what I think you are going for (the green "8-pt horizontal line" you see is the scrollView background color, which you see because there is an 8-pt
vertical constraint between the topView
and bottomView
):
The "bottom" gray view has a height constraint of 500-pts
, so we can scroll up:
Here is the code to create that:
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIScrollView *scrollView = [UIScrollView new];
UIView *topView = [UIView new];
UIView *bottomView = [UIView new];
UITextView *textView = [UITextView new];
UIStackView *stackView1 = [UIStackView new];
UIStackView *stackView2 = [UIStackView new];
scrollView.backgroundColor = [UIColor greenColor];
topView.backgroundColor = [UIColor redColor];
bottomView.backgroundColor = [UIColor lightGrayColor];
self.view.backgroundColor = [UIColor yellowColor];
scrollView.translatesAutoresizingMaskIntoConstraints = false;
topView.translatesAutoresizingMaskIntoConstraints = false;
bottomView.translatesAutoresizingMaskIntoConstraints = false;
textView.translatesAutoresizingMaskIntoConstraints = false;
stackView1.translatesAutoresizingMaskIntoConstraints = false;
stackView2.translatesAutoresizingMaskIntoConstraints = false;
// don't bounce the scroll view
scrollView.bounces = false;
// we want the textView to auto-size its height, so set it to non-scrolling
textView.scrollEnabled = NO;
// slightly bigger than default font
textView.font = [UIFont systemFontOfSize:18.0];
// stackView properties
stackView1.axis = UILayoutConstraintAxisVertical;
stackView2.axis = UILayoutConstraintAxisVertical;
stackView1.spacing = 5;
stackView1.distribution = UIStackViewDistributionFill;
stackView2.spacing = 5;
stackView2.distribution = UIStackViewDistributionFill;
// add the scrollView to the view
[self.view addSubview:scrollView];
// constrain scroll view to all 4 sides
[NSLayoutConstraint activateConstraints:
@[
[scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[scrollView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[scrollView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor],
[scrollView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor]
]
];
// add textView and both stack views to topView
[topView addSubview:textView];
[topView addSubview:stackView1];
[topView addSubview:stackView2];
// setup constraints for topView's subviews
[NSLayoutConstraint activateConstraints:
@[
// textView top, leading and trailing to topView with 8-pts "padding"
[textView.topAnchor constraintEqualToAnchor:topView.topAnchor constant:8.0],
[textView.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[textView.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// textView should be *at least* 200-pts tall, getting taller if enough text is added
[textView.heightAnchor constraintGreaterThanOrEqualToConstant:200.0],
// stackView1 top to text view bottom, leading and trailing to topView with 8-pts "padding"
[stackView1.topAnchor constraintEqualToAnchor:textView.bottomAnchor constant:8.0],
[stackView1.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView1.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// stackView2 top to stackView1 bottom, leading and trailing to topView with 8-pts "padding"
[stackView2.topAnchor constraintEqualToAnchor:stackView1.bottomAnchor constant:8.0],
[stackView2.leadingAnchor constraintEqualToAnchor:topView.leadingAnchor constant:8.0],
[stackView2.trailingAnchor constraintEqualToAnchor:topView.trailingAnchor constant:-8.0],
// and constrain stackView2 to bottom of topView with 8-pts padding
[stackView2.bottomAnchor constraintEqualToAnchor:topView.bottomAnchor constant:-8.0],
]
];
// now let's add some labels to the stack views
int numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor cyanColor];
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 1 \nwith more than one line", i];
[stackView1 addArrangedSubview:label];
}
numLabels = arc4random_uniform(3) + 2;
for (int i = 0; i < numLabels; i++){
UILabel *label = [UILabel new];
label.font = [UIFont systemFontOfSize:20];
label.numberOfLines = 0;
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor colorWithRed:1.0 green:0.75 blue:0.5 alpha:1.0]; // light-orange
label.text = [NSString stringWithFormat:@"Label %d\nIn stackView 2 \nwith more than one line", i];
[stackView2 addArrangedSubview:label];
}
Related Topics
How to Hide/Show Tabbar When Tapped Using Swift in iOS8
Compare Two Version Strings in Swift
Change Uidatepicker Font Color
Xcframework with Pods Dependencies
Crashlytics iOS - Log Caught Exception
Change Size of Uibarbuttonitem (Image) in Swift 3
How to Find Indexpath for Tapped Button in Tableview Using Seque
How to Center Crop an Image in Swiftui
Our App Crashed in iOS 9 Which Upload by Xcode 10
How to Calculate the Height of an Nsattributedstring with Given Width in iOS 6
How to Cast an Nsmutablearray to a Swift Array of a Specific Type
How to Select Range of Values When Using Arc4Random()
Adding Glow Effect to Uibutton - iOS
Swift Failed with Exit Code 1 While Compiling in Xcode - Possibly Related to Bridging-Headers