112 votes

SwiftUI HStack remplit toute la largeur avec un espacement égal.

J'ai un HStack :

struct BottomList: View {
    var body: some View {
        HStack() {
            ForEach(navData) { item in
                NavItem(image: item.icon, title: item.title)
            }
        }
    }
}

Comment centrer parfaitement son contenu avec un espacement égal remplissant automatiquement toute la largeur ?

Pour info, tout comme la classe CSS de Bootstraps .justify-content-around

206voto

svarrall Points 166

El frame modificateur de mise en page, avec .infinity para el maxWidth peut être utilisé à cet effet, sans qu'il soit nécessaire d'ajouter un paramètre Shape Voir.

struct ContentView: View {
    var data = ["View", "V", "View Long"]

    var body: some View {
    VStack {

        // This will be as small as possible to fit the data
        HStack {
            ForEach(data, id: \.self) { item in
                Text(item)
                    .border(Color.red)
            }
        }

        // The frame modifier allows the view to expand horizontally
        HStack {
            ForEach(data, id: \.self) { item in
                Text(item)
                    .frame(maxWidth: .infinity)
                    .border(Color.red)
            }
        }
    }
    }
}

Comparison using .frame modifier

23voto

anon Points 108

J'ai inséré Spacer() après chaque élément...mais pour le DERNIER élément, faites PAS ajouter un Spacer() :

struct BottomList: View {
    var body: some View {
        HStack() {
            ForEach(data) { item in
                Item(title: item.title)
                if item != data.last { // match everything but the last
                  Spacer()
                }
            }
        }
    }
}

Exemple de liste qui est uniformément espacée, même lorsque les largeurs des éléments sont différentes : enter image description here

(Note : Les réponses acceptées .frame(maxWidth: .infinity) n'a pas fonctionné dans tous les cas : il n'a pas fonctionné pour moi lorsqu'il s'agissait d'articles ayant des largeurs différentes)

18voto

John M. Points 5957

Les différents *Stack vont essayer de se réduire à la plus petite taille possible pour contenir leurs vues enfant. Si la vue enfant a une taille idéale, alors la fonction *Stack ne s'étendra pas pour remplir l'écran. Ce problème peut être résolu en plaçant chaque enfant au-dessus d'un écran transparent Rectangle dans un ZStack car un Shape se développera autant que possible. Un moyen pratique d'y parvenir est d'utiliser une extension sur View :

extension View {
    func inExpandingRectangle() -> some View {
        ZStack {
            Rectangle()
                .fill(Color.clear)
            self
        }
    }
}

Vous pouvez alors l'appeler comme ceci :

struct ContentView: View {
    var data = ["View", "View", "View"]

    var body: some View {
        VStack {

            // This will be as small as possible to fit the items
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .border(Color.red)
                }
            }

            // Each item's invisible Rectangle forces it to expand
            // The .fixedSize modifier prevents expansion in the vertical direction
            HStack {
                ForEach(data, id: \.self) { item in
                    Text(item)
                        .inExpandingRectangle()
                        .fixedSize(horizontal: false, vertical: true)
                        .border(Color.red)
                }
            }

        }
    }
}

Vous pouvez régler l'espacement sur le HStack comme souhaité.

Non-expanding and expanding stacks

12voto

Mojtaba Hosseini Points 2525

Si les éléments sont compatibles avec la pleine largeur, cela sera fait automatiquement, vous pouvez envelopper les éléments entre des intercalaires pour que cela se produise :

struct Resizable: View {
    let text: String

    var body: some View {
        HStack {
            Spacer()
            Text(text)
            Spacer()
        }
    }
}

SingleView

Donc vous. pouvez l'utiliser dans une boucle comme :

HStack {
    ForEach(data, id: \.self) { item in
        Resizable(text: item)
    }
}

MultiView

6voto

Wahab Khan Jadon Points 145

Vous pouvez également utiliser spacing en piles ... ie

HStack(spacing: 30){

            Image("NetflixLogo")
                .resizable()
                .scaledToFit()
                .frame(width: 40)

            Text("TV Show")
            Text("Movies")
            Text("My List")

        }
.frame(maxWidth: .infinity)

Le résultat de sortie ressemble à ceci ...

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X