Wyrównanie tekstu SwiftUI


90

Wśród wielu właściwości Text widoku nie znalazłem żadnych związanych z wyrównaniem tekstu. Widziałem w wersji demonstracyjnej, że automatycznie obsługuje RTL, a podczas umieszczania rzeczy za pomocą View bodyzawsze automatycznie centruje.

Czy brakuje mi jakiejś koncepcji dotyczącej systemu układu, SwiftUIa jeśli nie, w jaki sposób mogę ustawić właściwości wyrównania tekstu na Text?

Odpowiedzi:



85

Począwszy od wersji beta 3 SwiftUI, możesz wyśrodkować widok tekstu za pomocą modyfikatora ramki:

Text("Centered")
    .frame(maxWidth: .infinity, alignment: .center)

39

Próbowałem to zrozumieć, ponieważ inne odpowiedzi tutaj wspominają Text.multilineTextAlignment(_:)/ VStack(alignment:)/ frame(width:alignment:)ale każde rozwiązanie rozwiązuje konkretny problem. Ostatecznie zależy to od wymagań dotyczących interfejsu użytkownika i ich kombinacji.


VStack(alignment:)

alignmentTutaj jest dla wewnętrznych widoków w odpowiedni dla siebie.
Zatem sprecyzowanie .leadingskojarzyłoby wszystkie wewnętrzne poglądy tak, aby ich prowadzenie było wyrównane ze sobą.

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

wizerunek


.frame

W frame(width:alignment:)lub frame(maxWidth:alignment:)The alignmentjest za treści w obrębie danej szerokości.

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

Wewnętrzne widoki są wyrównane prowadząc odpowiednio względem siebie, ale same widoki są wyrównane na końcu odpowiednio do VStack.

wizerunek


.multilineTextAlignment

Określa to wyrównanie tekstu wewnątrz i jest najlepiej widoczne, gdy istnieje wiele wierszy bez zdefiniowanej definicji frame(width:alignment), szerokość jest automatycznie dostosowywana i wpływa na nią domyślne alignments.

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

wizerunek


Testy z kombinacjami:

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

wizerunek


1
To bardzo przekonująca odpowiedź. Dziękuję Ci. Rozważę również uznanie tej odpowiedzi za akceptowaną.
inokey

@inokey cieszę się, że mogę podzielić się moimi spostrzeżeniami :) Później znalazłem interesujący artykuł bardziej szczegółowo omawiający ogólne wyrównania widoku: Przewodniki wyrównania w SwiftUI
staticVoidMan

niesamowite rzeczy człowieku. SwiftUI naprawdę ewoluowało, odkąd pierwotnie opublikowałem to pytanie.
inokey

17

Właściwie napotkałem problem polegający na tym, że musiałem wyrównać tekst w jednej linii. Okazało się, że działa tak:

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

Jeśli połączysz to z parametrem szerokości ramki, możesz uzyskać ładne formatowanie bloku tekstu dla etykiet i tym podobnych.


14

zgaduję SwiftUI chce, żebyśmy używali opakowań takich jak stosy do takich rzeczy.

Dlatego zamiast pisać coś takiego Text("Hello World").aligned(.leading), zachęcamy do:

VStack(alignment: .leading) {
    Text("Hello World")
}

1
Więc nie mogę po prostu upuścić etykiety, która jest niezależna od stosu?
inokey

@inokey Przynajmniej nie znalazłem modyfikatora do tego.
fredpi

Ja też nie. Wydaje mi się, że brakuje mi jakiejś podstawowej koncepcji SUI. Nie mogę nawet upuścić tak „widoku” pomiędzy dwiema rzeczami i nadać mu koloru, jakby nie miały tam zwykłego obiektu a-la-uiview.
inokey

Modyfikator ramki ma parametr wyrównania
EmilioPelaez

Wydaje się głupie, że trzeba to zrobić (chociaż działa). Gdzie słyszałeś, że to było zachęcane?
MobileMon

6

Jeśli chcesz zachować stałą szerokość tekstu, „.multilineTextAlignment (.leading)” nie będzie działać, dopóki nie będzie tylko jeden wiersz tekstu.

To rozwiązanie, które u mnie zadziałało:

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


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

Stosowanie:

Text("Hello").leftAligned().frame(width: 300)

5

Musimy wyrównać tekst, a nie stos, w którym się znajduje. Więc dzwoniąc multilineTextAlignment(.center)i ustawiając limity linii, mogę zobaczyć teksty wyrównane do środka. Nie wiem, dlaczego muszę ustawiać limity linii, pomyślałem, że rozszerzy się, jeśli masz duży tekst.

Text("blahblah")
        .font(.headline)
        .multilineTextAlignment(.center)
        .lineLimit(50)

4

Możesz ustawić wyrównanie dla Vertical stackView jako wiodące. Jak poniżej

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

wprowadź opis obrazu tutaj


0

Chciałbym użyć widoku Spacer () do wyrównywania bloku tekstu. Ten przykład pokazuje tekst na końcowej stronie:

                HStack{
                    Spacer()
                    Text("Wishlist")
                }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.