Add Views In UIStackView Programmatically
Answer :
Stack views use intrinsic content size, so use layout constraints to define the dimensions of the views.
There is an easy way to add constraints quickly (example):
[view1.heightAnchor constraintEqualToConstant:100].active = true;
Complete Code:
- (void) setup { //View 1 UIView *view1 = [[UIView alloc] init]; view1.backgroundColor = [UIColor blueColor]; [view1.heightAnchor constraintEqualToConstant:100].active = true; [view1.widthAnchor constraintEqualToConstant:120].active = true; //View 2 UIView *view2 = [[UIView alloc] init]; view2.backgroundColor = [UIColor greenColor]; [view2.heightAnchor constraintEqualToConstant:100].active = true; [view2.widthAnchor constraintEqualToConstant:70].active = true; //View 3 UIView *view3 = [[UIView alloc] init]; view3.backgroundColor = [UIColor magentaColor]; [view3.heightAnchor constraintEqualToConstant:100].active = true; [view3.widthAnchor constraintEqualToConstant:180].active = true; //Stack View UIStackView *stackView = [[UIStackView alloc] init]; stackView.axis = UILayoutConstraintAxisVertical; stackView.distribution = UIStackViewDistributionEqualSpacing; stackView.alignment = UIStackViewAlignmentCenter; stackView.spacing = 30; [stackView addArrangedSubview:view1]; [stackView addArrangedSubview:view2]; [stackView addArrangedSubview:view3]; stackView.translatesAutoresizingMaskIntoConstraints = false; [self.view addSubview:stackView]; //Layout for Stack View [stackView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = true; [stackView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = true; }
Note: This was tested on iOS 9
Swift 5.0
//Image View let imageView = UIImageView() imageView.backgroundColor = UIColor.blue imageView.heightAnchor.constraint(equalToConstant: 120.0).isActive = true imageView.widthAnchor.constraint(equalToConstant: 120.0).isActive = true imageView.image = UIImage(named: "buttonFollowCheckGreen") //Text Label let textLabel = UILabel() textLabel.backgroundColor = UIColor.yellow textLabel.widthAnchor.constraint(equalToConstant: self.view.frame.width).isActive = true textLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true textLabel.text = "Hi World" textLabel.textAlignment = .center //Stack View let stackView = UIStackView() stackView.axis = NSLayoutConstraint.Axis.vertical stackView.distribution = UIStackView.Distribution.equalSpacing stackView.alignment = UIStackView.Alignment.center stackView.spacing = 16.0 stackView.addArrangedSubview(imageView) stackView.addArrangedSubview(textLabel) stackView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(stackView) //Constraints stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
Based on @user1046037 answer.
UIStackView
uses constraints internally to position its arranged subviews. Exactly what constraints are created depends on how the stack view itself is configured. By default, a stack view will create constraints that lay out its arranged subviews in a horizontal line, pinning the leading and trailing views to its own leading and trailing edges. So your code would produce a layout that looks like this:
|[view1][view2]|
The space that is allocated to each subview is determined by a number of factors including the subview's intrinsic content size and it's compression resistance and content hugging priorities. By default, UIView
instances don't define an intrinsic content size. This is something that is generally provided by a subclass, such as UILabel
or UIButton
.
Since the content compression resistance and content hugging priorities of two new UIView
instances will be the same, and neither view provides an intrinsic content size, the layout engine must make its best guess as to what size should be allocated to each view. In your case, it is assigning the first view 100% of the available space, and nothing to the second view.
If you modify your code to use UILabel
instances instead, you will get better results:
UILabel *label1 = [UILabel new]; label1.text = @"Label 1"; label1.backgroundColor = [UIColor blueColor]; UILabel *label2 = [UILabel new]; label2.text = @"Label 2"; label2.backgroundColor = [UIColor greenColor]; [self.stack1 addArrangedSubview:label1]; [self.stack1 addArrangedSubview:label2];
Note that it is not necessary to explictly create any constraints yourself. This is the main benefit of using UIStackView
- it hides the (often ugly) details of constraint management from the developer.
Comments
Post a Comment