objective example create code ios objective-c ios9 uistackview

ios - example - uistackview swift 3



Agregar vistas en UIStackView mediante programaciĆ³n (11)

Estoy tratando de agregar vistas en UIStackView mediante programació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 es de color negro (view1 también obtiene los parámetros para view2)


Acabo de encontrar un problema muy similar. Tal como se mencionó anteriormente, las dimensiones de la vista de pila dependen de un tamaño de contenido intrínseco de las subvistas organizadas. Aquí está mi solución en Swift 2.xy la siguiente estructura de vista:

vista - UIView

customView - CustomView: UIView

stackView - UISTackView

subvistas organizadas - subclases de UIView personalizadas

stackView.translatesAutoresizingMaskIntoConstraints = false;


En Swift 4.2

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


En mi caso, lo que estaba jugando con lo que esperaba era que me faltaba esta línea:

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

Después de eso, no es necesario establecer restricciones para mis subvistas organizadas, el stackview se encarga de eso.


Las vistas de pila utilizan el tamaño de contenido intrínseco, por lo tanto, use restricciones de diseño 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 fue probado en iOS 9


Para la respuesta aceptada cuando intenta ocultar cualquier vista dentro de la vista de pila, la restricción no funciona correctamente.

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

La razón es cuando ocultar la view en stackView establecerá la altura en 0 para animarla.

La solución cambia la priority restricción como se muestra a continuación.

let redView = UIView() redView.backgroundColor = .red let blueView = UIView() blueView.backgroundColor = .blue let stackView = UIStackView(arrangedSubviews: [redView, blueView]) stackView.axis = .vertical stackView.distribution = .fillEqually view.addSubview(stackView) // stackView.frame = CGRect(x: 0, y: 0, width: 200, height: 200) // autolayout constraint stackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([stackView.topAnchor.constraint(equalTo: view.topAnchor), stackView.leftAnchor.constraint(equalTo: view.leftAnchor), stackView.rightAnchor.constraint(equalTo: view.rightAnchor), stackView.heightAnchor.constraint(equalToConstant: 200)])


Pruebe el siguiente 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. Avíseme si necesita más aclaraciones.


Siguiendo dos líneas solucionó mi problema

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

Versión rápida -

self.stack1.distribution = UIStackViewDistributionFillEqually;


Tienes que establecer tu tipo de distribución. En su código, solo agregue:

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

O puede configurar la distribución directamente en su generador de interfaces. Por ejemplo:

Espero que ayude;) Lapinou.


UIStackView usa restricciones internamente para colocar sus subvistas organizadas. Exactamente qué restricciones se crean depende de cómo esté configurada la vista de la pila. De forma predeterminada, una vista de pila creará restricciones que expondrán sus subvistas organizadas en una línea horizontal, fijando las vistas iniciales y finales a sus propios bordes iniciales y finales. Entonces su código produciría un diseño similar a este:

|[view1][view2]|

El espacio que se asigna a cada subvista está determinado por una serie de factores, incluido el tamaño del contenido intrínseco de la subvista y su resistencia a la compresión y las prioridades de contenido. Por defecto, UIView instancias de UIView no definen un tamaño de contenido intrínseco. Esto es algo que generalmente proporciona una subclase, como UILabel o UIButton .

Dado que la resistencia a la compresión de contenido y las prioridades de abrazo de contenido de dos nuevas instancias de UIView serán las mismas, y ninguna de las vistas proporciona un tamaño de contenido intrínseco, el motor de diseño debe adivinar qué tamaño debe asignarse a cada vista. En su caso, está asignando a la primera vista el 100% del espacio disponible, y nada a la segunda vista.

Si modifica su código para usar instancias de 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 cuenta que no es necesario crear explícitamente ninguna restricción usted mismo. Este es el principal beneficio de usar UIStackView : oculta los detalles (a menudo feos) de la gestión de restricciones del desarrollador.


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 2.0 de Swift :

//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 la respuesta @ user1046037


//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 por @Oleg Popov