Agregar vistas en UIStackView mediante progtwigción

Estoy intentando agregar vistas en UIStackView mediante progtwigción. Por ahora mi código es:

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

Cuando implemento la aplicación, solo hay 1 vista y está en color negro. (View1 obtiene los parameters para view2 también)

Las vistas de stack utilizan el tamaño de contenido intrínseco, por lo que deben usar restricciones de layout para definir las dimensiones de las vistas.

Hay una manera fácil de agregar restricciones rápidamente (ejemplo):

 [view1.heightAnchor constraintEqualToConstant:100].active = true; 

Código completo:

 - (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; } 

Nota: esto se probó en iOS 9

UIStackView Espaciamiento Igual (centrado)

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 

Y aquí está la versión 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 

Basado en @ user1046037 answer

Siguiendo dos líneas arregló mi problema

  view.heightAnchor.constraintEqualToConstant(50).active = true; view.widthAnchor.constraintEqualToConstant(350).active = true; 

Versión 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 

Tienes que configurar tu tipo de distribución. En su código, juste add:

 self.stack1.distribution = UIStackViewDistributionFillEqually; 

O puede configurar la distribución directamente en el creador de la interfaz. Por ejemplo:

introduzca la descripción de la imagen aquí

Espero que eso ayude;) Lapinou.

UIStackView utiliza restricciones internamente para posicionar sus subvistas dispuestas. Exactamente qué restricciones se crean depende de cómo se configura la vista de stack misma. De forma pnetworkingeterminada, una vista de stack creará restricciones que diferencian sus subvistas dispuestas en una línea horizontal, fijando las vistas iniciales y posteriores a sus propios bordes iniciales y finales. Entonces su código produciría un layout que se parece a esto:

 |[view1][view2]| 

El espacio que se asigna a cada subvista está determinado por una serie de factores que incluyen el tamaño de contenido intrínseco de la subvista y sus prioridades de resistencia a la compression y de aarm de contenido. De forma pnetworkingeterminada, UIView instancias de UIView no definen un tamaño de contenido intrínseco. Esto es algo que generalmente proporciona una subclass, como UILabel o UIButton .

Dado que la resistencia a la compression de contenido y las prioridades de aarm de contenido de dos nuevas instancias de UIView serán las mismas, y ninguna vista proporciona un tamaño de contenido intrínseco, el motor de layout debe hacer su mejor conjetura sobre qué tamaño se debe asignar a cada vista. En su caso, se asigna la primera vista al 100% del espacio disponible y nada a la segunda vista.

Si modifica su código para usar UILabel instancias UILabel lugar, obtendrá mejores resultados:

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

Tenga en count que no es necesario crear explícitamente ninguna restricción usted mismo. Esta es la principal ventaja de usar UIStackView : oculta los detalles (a menudo feos) de la administración de restricciones del desarrollador.

  //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 

Mejorado en la respuesta de @Oleg Popov

Para la respuesta aceptada cuando intenta ocultar cualquier vista dentro de la vista de stack, la restricción funciona incorrectamente.

 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)>" ) 

La razón es cuando se oculta la view en stackView , se establecerá el alto en 0 para animarlo.

Solución cambie la priority la restricción como se muestra a continuación.

 import UIKit class ViewController: UIViewController { let stackView = UIStackView() let a = UIView() let b = UIView() override func viewDidLoad() { super.viewDidLoad() a.backgroundColor = UIColor.networking 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 } } 

Me encontré con un problema muy similar. Tal como se mencionó anteriormente, las dimensiones de la vista de stack dependen de un tamaño de contenido intrínseco de las subvistas dispuestas. Aquí está mi solución en Swift 2.xy la siguiente estructura de vista:

vista – UIView

customView – CustomView: UIView

stackView – UISTackView

Subvenciones arregladas: subclasss UIView personalizadas

  //: [Previous](@previous) import Foundation import UIKit import XCPlayground /**Container for stack view*/ class CustomView:UIView { override init(frame: CGRect) { super.init(frame: frame) } requinetworking 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() } requinetworking 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.networkingColor() 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 

Prueba debajo del código,

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

Espero que funcione. Por favor, avíseme si necesita más aclaraciones.