以编程方式在UIStackView中添加视图
我试图以编程方式在UIStackView中添加视图。 现在我的代码是:
UIView *view1 = [[UIView alloc]init]; view1.backgroundColor = [UIColor blackColor]; [view1 setFrame:CGRectMake(0, 0, 100, 100)]; UIView *view2 = [[UIView alloc]init]; view2.backgroundColor = [UIColor greenColor]; [view2 setFrame:CGRectMake(0, 100, 100, 100)]; [self.stack1 addArrangedSubview:view1]; [self.stack1 addArrangedSubview:view2];
当我部署应用程序时,只有1个视图,它是黑色的(view1也获取view2的参数)
堆栈视图使用内在内容大小,所以使用布局约束来定义视图的维度。
有一个简单的方法来快速添加约束(例如):
[view1.heightAnchor constraintEqualToConstant:100].active = true;
完整代码:
- (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; }
注意:这是在iOS 9上testing的
Swift 3.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 = UILayoutConstraintAxis.vertical stackView.distribution = UIStackViewDistribution.equalSpacing stackView.alignment = UIStackViewAlignment.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
这里是Swift 2.0版本:
//Image View let imageView = UIImageView() imageView.backgroundColor = UIColor.blueColor() imageView.heightAnchor.constraintEqualToConstant(120.0).active = true imageView.widthAnchor.constraintEqualToConstant(120.0).active = true imageView.image = UIImage(named: "buttonFollowCheckGreen") //Text Label let textLabel = UILabel() textLabel.backgroundColor = UIColor.yellowColor() textLabel.widthAnchor.constraintEqualToConstant(self.view.frame.width).active = true textLabel.heightAnchor.constraintEqualToConstant(20.0).active = true textLabel.text = "Hi World" textLabel.textAlignment = .Center //Stack View let stackView = UIStackView() stackView.axis = UILayoutConstraintAxis.Vertical stackView.distribution = UIStackViewDistribution.EqualSpacing stackView.alignment = UIStackViewAlignment.Center stackView.spacing = 16.0 stackView.addArrangedSubview(imageView) stackView.addArrangedSubview(textLabel) stackView.translatesAutoresizingMaskIntoConstraints = false; self.view.addSubview(stackView) //Constraints stackView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active = true stackView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active = true
基于@ user1046037的答案
以下两行解决了我的问题
view.heightAnchor.constraintEqualToConstant(50).active = true; view.widthAnchor.constraintEqualToConstant(350).active = true;
Swift版本 –
var DynamicView=UIView(frame: CGRectMake(100, 200, 100, 100)) DynamicView.backgroundColor=UIColor.greenColor() DynamicView.layer.cornerRadius=25 DynamicView.layer.borderWidth=2 self.view.addSubview(DynamicView) DynamicView.heightAnchor.constraintEqualToConstant(50).active = true; DynamicView.widthAnchor.constraintEqualToConstant(350).active = true; var DynamicView2=UIView(frame: CGRectMake(100, 310, 100, 100)) DynamicView2.backgroundColor=UIColor.greenColor() DynamicView2.layer.cornerRadius=25 DynamicView2.layer.borderWidth=2 self.view.addSubview(DynamicView2) DynamicView2.heightAnchor.constraintEqualToConstant(50).active = true; DynamicView2.widthAnchor.constraintEqualToConstant(350).active = true; var DynamicView3:UIView=UIView(frame: CGRectMake(10, 420, 355, 100)) DynamicView3.backgroundColor=UIColor.greenColor() DynamicView3.layer.cornerRadius=25 DynamicView3.layer.borderWidth=2 self.view.addSubview(DynamicView3) let yourLabel:UILabel = UILabel(frame: CGRectMake(110, 10, 200, 20)) yourLabel.textColor = UIColor.whiteColor() //yourLabel.backgroundColor = UIColor.blackColor() yourLabel.text = "mylabel text" DynamicView3.addSubview(yourLabel) DynamicView3.heightAnchor.constraintEqualToConstant(50).active = true; DynamicView3.widthAnchor.constraintEqualToConstant(350).active = true; let stackView = UIStackView() stackView.axis = UILayoutConstraintAxis.Vertical stackView.distribution = UIStackViewDistribution.EqualSpacing stackView.alignment = UIStackViewAlignment.Center stackView.spacing = 30 stackView.addArrangedSubview(DynamicView) stackView.addArrangedSubview(DynamicView2) stackView.addArrangedSubview(DynamicView3) stackView.translatesAutoresizingMaskIntoConstraints = false; self.view.addSubview(stackView) //Constraints stackView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active = true stackView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active = true
UIStackView
内部使用约束来定位排列的子视图。 究竟是什么约束创build取决于如何configuration堆栈视图本身。 默认情况下,堆栈视图将创build约束条件,将其排列的子视图布置在水平线中,将前导视图和尾视图固定到其自己的前缘和后缘。 所以你的代码会产生一个如下所示的布局:
|[view1][view2]|
分配给每个子视图的空间由许多因素决定,包括子视图的内在内容大小,压缩阻力和内容拥抱优先级。 默认情况下, UIView
实例不定义内在内容大小。 这是通常由子类提供的,如UILabel
或UIButton
。
由于两个新的UIView
实例的内容压缩抵抗和内容拥抱优先级将是相同的,并且这两个视图都不提供内在内容大小,所以布局引擎必须最好地猜测应该分配给每个视图的大小。 在你的情况下,它是分配第一个视图100%的可用空间,没有什么第二个视图。
如果你修改你的代码来使用UILabel
实例,你会得到更好的结果:
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];
请注意,没有必要明确地自行创build任何约束条件。 这是使用UIStackView
的主要好处 – 它隐藏了开发人员的约束pipe理(经常是丑陋的)细节。
你必须设置你的分配types。 在你的代码中,juste add:
self.stack1.distribution = UIStackViewDistributionFillEqually;
或者您可以直接在界面构build器中设置分配。 例如:
希望有所帮助;)拉皮诺。
//Image View let imageView = UIImageView() imageView.backgroundColor = UIColor.blueColor() imageView.heightAnchor.constraintEqualToConstant(120.0).active = true imageView.widthAnchor.constraintEqualToConstant(120.0).active = true imageView.image = UIImage(named: "buttonFollowCheckGreen") //Text Label let textLabel = UILabel() textLabel.backgroundColor = UIColor.greenColor() textLabel.widthAnchor.constraintEqualToConstant(self.view.frame.width).active = true textLabel.heightAnchor.constraintEqualToConstant(20.0).active = true textLabel.text = "Hi World" textLabel.textAlignment = .Center //Third View let thirdView = UIImageView() thirdView.backgroundColor = UIColor.magentaColor() thirdView.heightAnchor.constraintEqualToConstant(120.0).active = true thirdView.widthAnchor.constraintEqualToConstant(120.0).active = true thirdView.image = UIImage(named: "buttonFollowMagenta") //Stack View let stackView = UIStackView() stackView.axis = UILayoutConstraintAxis.Vertical stackView.distribution = UIStackViewDistribution.EqualSpacing stackView.alignment = UIStackViewAlignment.Center stackView.spacing = 16.0 stackView.addArrangedSubview(imageView) stackView.addArrangedSubview(textLabel) stackView.addArrangedSubview(thirdView) stackView.translatesAutoresizingMaskIntoConstraints = false; self.view.addSubview(stackView) //Constraints stackView.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active = true stackView.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active = true
通过@Oleg Popov改进了答案
对于您尝试隐藏堆栈视图内的任何视图时的接受答案,约束工作不正确。
Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x618000086e50 UIView:0x7fc11c4051c0.height == 120 (active)>", "<NSLayoutConstraint:0x610000084fb0 'UISV-hiding' UIView:0x7fc11c4051c0.height == 0 (active)>" )
原因是当在stackView
view
中隐藏view
,它会将高度设置为0来为其设置animation效果。
解决scheme如下更改约束priority
。
import UIKit class ViewController: UIViewController { let stackView = UIStackView() let a = UIView() let b = UIView() override func viewDidLoad() { super.viewDidLoad() a.backgroundColor = UIColor.red a.widthAnchor.constraint(equalToConstant: 200).isActive = true let aHeight = a.heightAnchor.constraint(equalToConstant: 120) aHeight.isActive = true aHeight.priority = 999 let bHeight = b.heightAnchor.constraint(equalToConstant: 120) bHeight.isActive = true bHeight.priority = 999 b.backgroundColor = UIColor.green b.widthAnchor.constraint(equalToConstant: 200).isActive = true view.addSubview(stackView) stackView.backgroundColor = UIColor.blue stackView.addArrangedSubview(a) stackView.addArrangedSubview(b) stackView.axis = .vertical stackView.distribution = .equalSpacing stackView.translatesAutoresizingMaskIntoConstraints = false } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // Just add a button in xib file or storyboard and add connect this action. @IBAction func test(_ sender: Any) { a.isHidden = !a.isHidden } }
我刚碰到类似的问题。 就像之前提到的,堆栈视图的尺寸取决于排列的子视图的一个固有内容大小。 这里是我的解决scheme在Swift 2.x和下面的视图结构:
视图 – UIView
customView – CustomView:UIView
stackView – UISTackView
排列子视图 – 自定义UIView子类
//: [Previous](@previous) import Foundation import UIKit import XCPlayground /**Container for stack view*/ class CustomView:UIView { override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } init(){ super.init(frame: CGRectZero) } } /**Custom Subclass*/ class CustomDrawing:UIView{ override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } func setup(){ // self.backgroundColor = UIColor.clearColor() print("setup \(frame)") } override func drawRect(rect: CGRect) { let ctx = UIGraphicsGetCurrentContext() CGContextMoveToPoint(ctx, 0, 0) CGContextAddLineToPoint(ctx, CGRectGetWidth(bounds), CGRectGetHeight(bounds)) CGContextStrokePath(ctx) print("DrawRect") } } //: [Next](@next) let stackView = UIStackView() stackView.distribution = .FillProportionally stackView.alignment = .Center stackView.axis = .Horizontal stackView.spacing = 10 //container view let view = UIView(frame: CGRectMake(0,0,320,640)) view.backgroundColor = UIColor.darkGrayColor() //now custom view let customView = CustomView() view.addSubview(customView) customView.translatesAutoresizingMaskIntoConstraints = false customView.widthAnchor.constraintEqualToConstant(220).active = true customView.heightAnchor.constraintEqualToConstant(60).active = true customView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true customView.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true customView.backgroundColor = UIColor.lightGrayColor() //add a stack view customView.addSubview(stackView) stackView.centerXAnchor.constraintEqualToAnchor(customView.centerXAnchor).active = true stackView.centerYAnchor.constraintEqualToAnchor(customView.centerYAnchor).active = true stackView.translatesAutoresizingMaskIntoConstraints = false let c1 = CustomDrawing() c1.translatesAutoresizingMaskIntoConstraints = false c1.backgroundColor = UIColor.redColor() c1.widthAnchor.constraintEqualToConstant(30).active = true c1.heightAnchor.constraintEqualToConstant(30).active = true let c2 = CustomDrawing() c2.translatesAutoresizingMaskIntoConstraints = false c2.backgroundColor = UIColor.blueColor() c2.widthAnchor.constraintEqualToConstant(30).active = true c2.heightAnchor.constraintEqualToConstant(30).active = true stackView.addArrangedSubview(c1) stackView.addArrangedSubview(c2) XCPlaygroundPage.currentPage.liveView = view
尝试下面的代码,
UIView *view1 = [[UIView alloc]init]; view1.backgroundColor = [UIColor blackColor]; [view1 setFrame:CGRectMake(0, 0, 50, 50)]; UIView *view2 = [[UIView alloc]init]; view2.backgroundColor = [UIColor greenColor]; [view2 setFrame:CGRectMake(0, 100, 100, 100)]; NSArray *subView = [NSArray arrayWithObjects:view1,view2, nil]; [self.stack1 initWithArrangedSubviews:subView];
希望它的作品。 请让我知道,如果你需要更多的澄清。