Aprende a crear UIStackView en UIKit
Aprende a crear UIStackView en UIKit

UIStackView en UIKit con Swift en Español - Curso iOS

Un UIStackView en UIKit sirve para agrupar vistas una al lado de la otra, o una debajo de la otra con el mínimo esfuerzo. Esto significa que nosotros no nos encargamos de añadir las constraints de Auto Layout, sino que lo hace el UIStackView por nosotros.

SwiftBeta

Tabla de contenido

UIStackView en UIKit con Swift

Hoy en SwiftBeta vamos a crear nuestro primer UIStackView. Los UIStackViews nos sirven para colocar una colección de vistas una encima de otra, o una al lado de la otra, depende de como configuremos nuestro StackView, si horizontal o vertical. Vamos a ver estas dos configuraciones en el post de hoy. Al usar un UIStackView nos ahorramos crear las constraints de sus subvistas, ya que el StackView lo hace por nosotros. Es decir, si queremos apilar una serie de vistas, el UIStackView lo hace por nosotros. Como ejemplo práctico vamos a crear una vista que va a simular una pantalla de In App Purchases, donde un user podrá seleccionar el precio de la In App Purchase que quiere consumir dentro de nuestra app.

Creamos el proyecto en Xcode

Lo primero de todo que vamos hacer es crear el proyecto en Xcode. Recurda seleccionar como interfaz Storyboard (UIKit). Y una vez creado el proyecto nos vamos al ViewController. Allí dentro vamos a crear nuestro primer UIStackView.

class ViewController: UIViewController {    
    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(swiftBetaStackView)
        
        NSLayoutConstraint.activate([
            swiftBetaStackView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
            swiftBetaStackView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            swiftBetaStackView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
        ])
    }
}
Creamos nuestro primer UIStackView

Hemos creado nuestro UIStackView, lo hemos añadido a la vista del ViewController y hemos añadido las constraints. Ahora mismo las vistas de nuestro StackView están vacías. Lo que vamos hacer es crear varios UIButton y los vamos a añadir a las arrangedSubviews del StackView.

class ViewController: UIViewController {    
    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false        
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(swiftBetaStackView)
        
        NSLayoutConstraint.activate([            
            swiftBetaStackView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
            swiftBetaStackView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            swiftBetaStackView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
        ])
        
        ["1.99€", "2.99€", "14.99€", "24.99€"].forEach { price in
            let button = UIButton(type: .system)
            var configuration = UIButton.Configuration.borderedTinted()
            configuration.title = price
            configuration.subtitle = "Suscripción"
            configuration.image = UIImage(systemName: "eurosign.circle.fill")
            configuration.imagePadding = 12
            configuration.baseBackgroundColor = .systemBlue
            button.configuration = configuration
            
            swiftBetaStackView.addArrangedSubview(button)
        }
    }
}
Añadimos subvistas a nuestro UIStackView

Ahora si compilamos, vamos a ver el resultado de nuestro StackView con los UIButtons que hemos añadido.

Resultado de un UIStackView en el eje horizontal
Resultado de un UIStackView en el eje horizontal

En el simulador aparece que nuestro StackView ha distribuido las vistas una al lado de la otra, pero podemos especificar el eje vertical o horizontal. En este caso, por defecto es el eje horizontal, vamos a cambiar esta propiedad en nuestro StackView.

    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        
        return stackView
    }()
Cambiamos el eje de nuestro UIStackView al eje vertical
Simulador mostrando subvistas apiladas dentor de un UIStackView
Simulador mostrando subvistas apiladas dentor de un UIStackView

Si te fijas, ahora en lugar de añadir un UIButton uno al lado del otro, lo que ha hecho ha sido poner uno encima del otro. Pero, aún podemos configurar más parámetros de nuestro UIStackView, como por ejemplo el margen que queremos entre las vistas que hay dentro del StackView. Para ello, vamos a modificar un propiedad llamada spacing del UIStackView.

    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.spacing = 20
        return stackView
    }()
Añadimos espacio entre las subvistas de un UIStackView

Vamos a compilar y vamos a ver el resultado

UIStackView con espacio de 20 entre las vistas que contiene
UIStackView con espacio de 20 entre las vistas que contiene

Poco a poco ya va cogiendo forma nuestro UIStackView. Puedes jugar con más propiedades dentro del StackView, como por ejemplo el alignment o la distribución. Vamos a ver la primera, si añadimos un alignment de leading, center o trailing podemos ver como cambiar el tamaño de nuestros UIButtons dentro del StackView:

    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.spacing = 20
        stackView.alignment = .leading
        return stackView
    }()
Modificar el alignment de un UIStackView: .leading, .trailing, .center

Vamos a compilar nuestra aplicación para ver el resultado:

UIStackView con .leading alignment
UIStackView con .leading alignment

Vamos a borrar el alignment, y vamos a continuar. Lo que vamos hacer ahora es añadir un UILabel. Este UILabel será el título de nuestra pantall:

class ViewController: UIViewController {
    private let swiftBetaLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "🤑 In App Purchases 🤑"
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 32)
        return label
    }()
    
    private let swiftBetaStackView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.spacing = 20
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(swiftBetaLabel)
        view.addSubview(swiftBetaStackView)
        
        NSLayoutConstraint.activate([
            swiftBetaLabel.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: 20),
            swiftBetaLabel.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            swiftBetaLabel.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
            
            swiftBetaStackView.topAnchor.constraint(equalTo: swiftBetaLabel.bottomAnchor, constant: 32),
            swiftBetaStackView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor),
            swiftBetaStackView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor),
        ])
        
        ["1.99€", "2.99€", "14.99€", "24.99€"].forEach { price in
            let button = UIButton(type: .system)
            var configuration = UIButton.Configuration.borderedTinted()
            configuration.title = price
            configuration.subtitle = "Suscripción"
            configuration.image = UIImage(systemName: "eurosign.circle.fill")
            configuration.imagePadding = 12
            configuration.baseBackgroundColor = .systemBlue
            button.configuration = configuration
            
            swiftBetaStackView.addArrangedSubview(button)
        }
    }
}
Añadimos un UILabel y lo añadimos a nuestro UIViewController

Si compilamos la aplicación este sería el resultado:

Vista con UILabel y UIStackView en UIKit
Vista con UILabel y UIStackView en UIKit

Justo lo que queríamos!

Conclusión

Hoy hemos aprendido a crear un UIStackView y hemos visto lo fácil que es añadir subvistas dentro de él. Es fácil y simple, nos ahorramos añadir constraints para posicionar todas las subvistas.

Si quieres seguir aprendiendo sobre SwiftUI, Swift, Xcode, o cualquier tema relacionado con el ecosistema Apple