Alignement de texte SwiftUI

90

Parmi les nombreuses propriétés de la Textvue, je n'ai pas trouvé de propriétés liées à l'alignement du texte. J'ai vu dans une démo qu'il gère automatiquement RTL, et lors du placement de choses à l'aide de View body, il le centre toujours automatiquement.

Y a-t-il un concept qui me manque à propos du système de mise en page SwiftUIet sinon, comment puis-je définir les propriétés d'alignement du texte sur le Text?

inokey
la source

Réponses:

144

Vous pouvez le faire via le modificateur .multilineTextAlignment(.center).

Documentation Apple

vrwim
la source
8
Y a-t-il quelque chose pour justifier le texte?
theMouk
85

À partir de SwiftUI beta 3, vous pouvez centrer une vue de texte avec le modificateur de cadre:

Text("Centered")
    .frame(maxWidth: .infinity, alignment: .center)
Jim Marquardt
la source
39

J'essayais de comprendre cela moi-même comme d'autres réponses mentionnent ici Text.multilineTextAlignment(_:)/ VStack(alignment:)/ frame(width:alignment:)mais chaque solution résout un problème spécifique. Finalement, cela dépend des exigences de l'interface utilisateur et d'une combinaison de celles-ci.


VStack(alignment:)

Le alignmentvoici pour les vues intérieures les unes par rapport aux autres.
Ainsi, la spécification .leadingassocierait toutes les vues intérieures pour que leur direction soit alignée les unes sur les autres.

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
        .background(Color.gray.opacity(0.2))
  Text("sit amet")
        .background(Color.gray.opacity(0.2))
}
.background(Color.gray.opacity(0.1))

image


.frame

Dans frame(width:alignment:)ou frame(maxWidth:alignment:), le alignmentest pour le contenu dans la largeur donnée.

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
      .background(Color.gray.opacity(0.2))
  Text("sit amet")
      .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

Les vues intérieures sont alignées en tête respectivement les unes par rapport aux autres mais les vues elles-mêmes sont alignées en arrière respectivement par rapport au VStack.

image


.multilineTextAlignment

Cela spécifie l'alignement du texte à l'intérieur et peut être mieux vu lorsqu'il y a plusieurs lignes sinon sans définition frame(width:alignment), la largeur est automatiquement ajustée et est affectée par les valeurs par défaut alignment.

VStack(alignment: .trailing, spacing: 6) {
  Text("0. automatic frame\n+ view at parent's specified alignment\n+ multilineTA not set by default at leading")
    .background(Color.gray.opacity(0.2))
  Text("1. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .background(Color.gray.opacity(0.2))
  Text("2. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

image


Tests avec combinaisons:

VStack(alignment: .trailing, spacing: 6) {
  Text("1. automatic frame, at parent's alignment")
  .background(Color.gray.opacity(0.2))
  Text("2. given full width & leading alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .leading)
  .background(Color.gray.opacity(0.2))
  Text("3. given full width & center alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("4. given full width & center alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("5. given full width & center alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("6. given full width but no alignment\n+ multilineTA at default leading\n+ leading is based on content, looks odd sometimes as seen here")
  .frame(maxWidth: .infinity)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380)
.background(Color.gray.opacity(0.1))

image

staticVoidMan
la source
1
C'est une réponse très convaincante. Merci. J'envisagerai également d'en faire une réponse acceptée.
inokey
@inokey heureux de partager mes observations :) J'ai trouvé plus tard un article intéressant qui approfondissait les alignements de vue en général: Guides d'alignement dans SwiftUI
staticVoidMan
homme de trucs génial. SwiftUI a vraiment évolué depuis que j'ai initialement publié cette question.
inokey
17

En fait, j'ai rencontré le problème où je devais aligner le texte sur une seule ligne. Voici ce que j'ai trouvé pour fonctionner:

Text("some text")
    .frame(alignment: .leading)

Si vous combinez cela avec le paramètre de largeur de cadre, vous pouvez obtenir une bonne mise en forme de bloc de texte pour les étiquettes et autres.

Lekyaira
la source
14

Je suppose SwiftUIque nous voulons que nous utilisions des emballages comme des piles pour de telles choses.

Donc, au lieu d'écrire quelque chose comme Text("Hello World").aligned(.leading), ce qui suit est encouragé:

VStack(alignment: .leading) {
    Text("Hello World")
}
Fredpi
la source
1
Je ne peux donc pas simplement supprimer une étiquette indépendante de la pile?
inokey le
@inokey Je n'ai pas trouvé de modificateur pour cela au moins.
fredpi
Moi non plus. Il me semble que je manque une sorte de concept de base de SUI. Je ne peux même pas laisser tomber comme juste la "vue" entre deux choses, et lui donner une couleur, comme s'ils n'avaient pas d'objet a-la-uiview simple là-dedans.
inokey le
Le modificateur de cadre a un paramètre d'alignement
EmilioPelaez
Cela semble idiot d'avoir à faire (même si cela fonctionne). Où avez-vous entendu dire que cela était encouragé?
MobileMon
6

Si vous souhaitez conserver une largeur constante pour le texte, le ".multilineTextAlignment (.leading)" ne prendra aucun effet tant qu'il n'y aura qu'une seule ligne de texte.

C'est la solution qui a fonctionné pour moi:

struct LeftAligned: ViewModifier {
    func body(content: Content) -> some View {
        HStack {
            content
            Spacer()
        }
    }
}


extension View {
    func leftAligned() -> some View {
        return self.modifier(LeftAligned())
    }
}

Usage:

Text("Hello").leftAligned().frame(width: 300)
Kamil Zaborowski
la source
5

Nous devons aligner le texte et non la pile dans laquelle il se trouve. Ainsi, en appelant multilineTextAlignment(.center)et en définissant les limites de ligne, je peux voir les textes alignés au centre. Je ne sais pas pourquoi je dois définir les limites de ligne, j'ai pensé que cela augmenterait si vous aviez un texte volumineux.

Text("blahblah")
        .font(.headline)
        .multilineTextAlignment(.center)
        .lineLimit(50)
Miki
la source
4

Vous pouvez définir l'alignement pour Vertical stackView comme leader. Comme ci-dessous

 VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            Text("Joshua Tree National Park")
                .font(.subheadline)
        }

entrez la description de l'image ici

Kathiresan Murugan
la source
0

Je voudrais utiliser la vue Spacer () pour aligner le bloc de texte. Cet exemple montre le texte à la fin:

                HStack{
                    Spacer()
                    Text("Wishlist")
                }
Oleksii Radetskyi
la source