Nous avons vu dans l‘introduction à SwiftUI que notre application était composée de View. Mais à l’intérieur de celles-ci, nous utilisons des dispositions de vues pour organiser les différents éléments qui les composent.

Nous allons donc parler aujourd’hui de HStack, VStack et ZStack que tu utiliseras forcément dans ton application mobile iOS. Alors, mets ton casque de chantier, c’est parti pour la construction de tes vues !

Disposition des éléments dans les différentes piles (Stacks)

Illustration issue de la documentation Apple officielle

HStack

C’est une vue qui arrange les éléments de manière horizontale.

struct TextView: View {
    var body: some View {
        HStack{
            Image("Break_time")
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text("Ceci est un titre")
                .font(.title)
            Text("Et ceci une légende")
                .font(.subheadline)
        }
    }
}

On aligne bien horizontalement tous les éléments qui se trouvent dans la HStack.

LazyHStack

Il est possible de charger une vue (ou une partie de vue) uniquement lorsqu’elle est affichée pour la première fois. Pour cela, nous utilisons LazyHStack (quand la vue est horizontale). Ce peut être utile avec une longue liste, par exemple. Mais attention à ce qu’on affiche car la vue, une fois affichée, reste en mémoire.

Il est également à prendre en compte le fait que la LazyHStack permet de scroller en utilisant les « espaces blancs » autour de notre élément. La HStack normale ne prendre en compte que le scroll sur l’élément.

VStack

La VStack est la vue qui arrange les éléments de manière verticale.

struct TextView: View {
    var body: some View {
        VStack{
            Image("Break_time")
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text("Ceci est un titre")
                .font(.title)
            Text("Et ceci une légende")
                .font(.subheadline)
        }
    }
}

LazyVStack

Comme pour la LazyHStack, mais en version verticale 😉 Tu veux un exemple visuel un peu plus parlant ? Va voir ce post LinkedIn.

VStack & HStack avec deux vues

struct ImageViewWithText: View {
    var body: some View {
        VStack {
            Image("Break_time")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .overlay(TextDetailsView(), alignment: .bottom)
        }
    }
}

struct TextDetailsView: View {
    var body: some View {
            HStack {
                VStack(alignment: .leading) {
                    Text("Quand on construit des vues")
                        .font(.title)
                    Text("C'est bien de faire des pauses")
                        .font(.subheadline)
                }
                Spacer()
            }
            .padding()
            .foregroundColor(.primary)
            .background(Color.primary
                .colorInvert()
                .opacity(0.75))
    }
}

Ici nous utilisons la VStack pour afficher l’image avec l’attribut Image. Par dessus, nous lui fixons la légende de l’image grâce à la méthode overlay() qui appelle une autre vue.

La méthode Spacer() permet à la HStack de prendre toute la largeur de l’appareil car il ajoute un « espace » après celle-ci.

ZStack

C’est une vue qui recouvre les sous-vues, en les alignant sur les deux axes. Elle attribue à chaque vue secondaire successive une valeur d’axe Z supérieure à la vue précédente. C’est à dire que les nouvelles vues apparaissent au-dessus des vues créées en premières.

Dans l’exemple précédent, nous aurions pu ajouter une ZStack qui aurait permis d’ajouter les éléments les uns sur les autres. Mais grâce à l’appel de la fonction overlay(), le code est moins surchargé et plus lisible.

struct TextView: View {
    var body: some View {
        ZStack{
            Image("Break_time") // Créé en premier donc en dessous des autres éléments
                .resizable()
                .aspectRatio(contentMode: .fit)
            Text("Je suis l'élément du milieu") // Couleur de fond jaune
                .font(.title)
                .background(.yellow)
            Text("Dernier élément")
                .font(.subheadline)
                .background(.red) // Couleur de fond rouge
        }
    }
}

Dans cet exemple, le premier élément déclaré est l’image. C’est à dire qu’elle sera au dernier plan.
Le titre est déclaré ensuite avec un fond jaune. C’est donc un élément qui se place au dessus de l’image.
Enfin, le Text en légende est le dernier élément créé, avec un fond rouge. C’est comme si on le posait simplement au-dessus de la pile qui existe déjà.

Les 3 piles ensembles

Si j’ai créé une vue avec une HStack et une VStack, je peux ajouter une ZStack afin d’ajouter un fond coloré à l’ensemble de mon appareil. Comme si je créais un background-color pour l’ensemble de ma page en CSS.

struct TextDetailsView: View {
    var body: some View {
        ZStack{
            Rectangle() // Remplis tout le fond d'écran de l'appareil
                .fill(Gradient(colors: [.indigo, .purple])) // Dégradé
                .ignoresSafeArea()
            HStack {
                VStack(alignment: .center) { // Alignement au centre
                    Text("Ceci est un titre")
                        .font(.title)
                    Text("Ceci est une légende")
                        .font(.subheadline)
                }
                .frame(maxWidth: .infinity) // Remplis l'espace 
            }
            .padding()
            .foregroundColor(.primary)
            .background(Color.primary
                .colorInvert()
                .opacity(0.75))
        }
    }
}

Sympa, non ?


Ça y est. Tu as compris comment construire tes premières vues ! N’hésites pas à cliquer sur la petite pomme  à côté des titres, elles te renverront directement à la documentation officielle !

Je t’invite également à suivre ce sujet sur StackOverflow qui parle justement des 3 différentes dispositions de vues (tu reconnaîtras peut-être le dernier dégradé 😉). Il te permettra également de trouver des alternatives pour organiser tes vues.

N’hésites pas à t’entraîner pour bien comprendre le fonctionnement de ces dispositions !

Si tu as aimé cet article, partage le 🫶