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?

inokey
źródło

Odpowiedzi:

144

Możesz to zrobić za pomocą modyfikatora .multilineTextAlignment(.center).

Dokumentacja Apple

vrwim
źródło
8
Czy istnieje coś, co uzasadnia tekst?
theMouk
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)
Jim Marquardt
źródło
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

staticVoidMan
źródło
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.

Lekyaira
źródło
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")
}
fredpi
źródło
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)
Kamil Zaborowski
źródło
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)
Miki
źródło
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

Kathiresan Murugan
źródło
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")
                }
Oleksii Radetskyi
źródło