Allineamento del testo SwiftUI


97

Tra le molte proprietà della Textvista, non sono riuscito a trovare nessuna relativa all'allineamento del testo. Ho visto in una demo che gestisce automaticamente l'RTL e quando si posiziona qualcosa utilizzando View's body, lo centra sempre automaticamente.

C'è qualche concetto che mi manca sul sistema di layout SwiftUIe, in caso contrario, come posso impostare le proprietà di allineamento del testo su Text?

Risposte:



96

Da SwiftUI beta 3 in avanti, puoi centrare una visualizzazione di testo con il modificatore di frame:

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

50

Stavo cercando di capirlo da solo mentre altre risposte qui menzionano Text.multilineTextAlignment(_:)/ VStack(alignment:)/ frame(width:alignment:)ma ogni soluzione risolve un problema specifico. Alla fine dipende dai requisiti dell'interfaccia utente e da una combinazione di questi.


VStack(alignment:)

Il alignmentqui è per le viste interiori l'una rispetto all'altra.
Quindi la specifica .leadingassocia tutte le viste interne per avere la loro interlinea allineata l'una con l'altra.

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

Immagine


.frame

In frame(width:alignment:)o frame(maxWidth:alignment:), alignmentè per i contenuti entro la larghezza data.

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

Le viste interne sono allineate in prima linea l'una rispetto all'altra, ma le viste stesse sono allineate in coda rispetto alle VStack.

Immagine


.multilineTextAlignment

Questo specifica l'allineamento del testo all'interno e può essere visto meglio quando ci sono più righe altrimenti senza un definito frame(width:alignment), la larghezza viene regolata automaticamente e viene influenzata dalle alignments di default .

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

Immagine


Test con combinazioni:

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

Immagine


1
Questa è una risposta molto convincente. Grazie. Prenderò in considerazione l'idea di rendere anche questa una risposta accettata.
inokey

1
@inokey felice di condividere le mie osservazioni :) In seguito ho trovato un articolo interessante che approfondisce gli allineamenti delle viste in generale: Guide di allineamento in SwiftUI
staticVoidMan

roba fantastica uomo. SwiftUI si è davvero evoluto da quando ho inizialmente pubblicato quella domanda.
inokey

17

In realtà mi sono imbattuto nel problema in cui dovevo allineare il testo su una singola riga. Quello che ho scoperto funzionare è questo:

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

Se lo combini con il parametro della larghezza della cornice puoi ottenere una bella formattazione del blocco di testo per etichette e simili.


15

Immagino che SwiftUIvoglia che usiamo wrapper come stack per queste cose.

Quindi, invece di scrivere qualcosa di simile Text("Hello World").aligned(.leading), si incoraggia quanto segue:

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

1
Quindi non posso semplicemente rilasciare un'etichetta indipendente dallo stack?
inokey

@inokey non ho trovato un modificatore almeno per questo.
fredpi

Neanche io. Mi sembra che mi manchi una sorta di concetto di base della SUI. Non posso nemmeno lasciar cadere come la "vista" tra due cose e dargli un colore, come se non avessero un semplice oggetto a-la-uiview lì dentro.
inokey

Il modificatore di frame ha un parametro di allineamento
EmilioPelaez

Sembra sciocco aver a che fare (anche se funziona). Dove hai sentito che questo è stato incoraggiato?
MobileMon

7

Dobbiamo allineare il testo e non la pila in cui si trova. Quindi chiamando multilineTextAlignment(.center)e impostando i limiti di linea posso essere in grado di vedere i testi allineati al centro. Non so perché devo impostare i limiti di riga, ho pensato che si espanderebbe se avessi un testo di grandi dimensioni.

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

6

Se desideri mantenere la larghezza costante per il testo, ".multilineTextAlignment (.leading)" non avrà alcun effetto finché non sarà presente una sola riga di testo.

Questa è la soluzione che ha funzionato per me:

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


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

Utilizzo:

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

4

È possibile impostare l'allineamento per StackView verticale come interlinea. Come sotto

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

inserisci qui la descrizione dell'immagine


2

Vorrei usare la Spacer()vista per allineare il blocco di testo. Questo esempio mostra il testo sul lato finale:

HStack{
    Spacer()
    Text("Wishlist")
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.