Com Hstack exposa els seus fills · objc.io

En la seva major part, el sistema de disseny SwiftUI és intuïtiu d’utilitzar, cosa que us permet aconseguir el que voleu amb poca experimentació. De vegades, però, us trobeu amb comportaments difícils de pensar sense una comprensió més profunda del rendiment bàsic.

HStack

Són un bon exemple d’això: la majoria de les vegades funcionen com s’espera, però de vegades el seu comportament pot resultar desconcertant. Una bona manera de reduir aquest trencaclosques és intentar reproduir el vostre propi comportament. Mitjançant un procés de convergència cada vegada més proper, podem entendre millor els mecanismes bàsics.

En aquest article en parlarem HStack
, però s’aplica la mateixa lògica a VStack
excepte que els eixos estan invertits.

Comencem per un exemple senzill que es comporta exactament com s’esperava:

								HStack(spacing: 0) {
    Rectangle().fill(Color.red)
    Rectangle().fill(Color.green)
    Rectangle().fill(Color.blue)
}
.frame(width: 300, height: 100)

							

Cada visualització té una amplada de 100 punts. La vora negra mostra els límits de la pila.

Per entendre el comportament del disseny SwiftUI mitjançant experiments, és útil visualitzar les dimensions de la vista. Podem crear un assistent senzill per cobrir l’amplada de la vista:

								extension View {
    func measure() -> some View {
        overlay(GeometryReader { proxy in
            Text("(Int(proxy.size.width))")
        })
    }
}

							

Afegint un fitxer .measure()
per a cadascun dels tres subexàmens obtenim la imatge següent:

Fins ara, tot bé. Les coses es posen interessants quan afegim vistes amb una flexibilitat diferent.

Per exemple, tingueu en compte el següent:

								HStack(spacing: 0) {
    Rectangle().fill(Color.red).frame(maxWidth: 100).measure()
    Rectangle().fill(Color.green).frame(minWidth: 100).measure()
}.frame(width: 150, height: 100)

							

Quina amplitud tenen les opinions individuals?

Si esteu acostumat a un disseny basat en restriccions, podeu pensar així: hi ha 150 punts d’espai lliure i el nen verd hauria de tenir almenys 100 d’amplada. Per tant, establir el nen vermell a l’amplada 50 resol totes les restriccions. Tot i això, no és en absolut el cas HStack
exposar el seu contingut.

Com veiem a continuació, el rectangle vermell fa 75 d’amplada i el rectangle verd de 100 d’amplada. HStack fins i tot va més enllà del seu recinte.

Per què passa això? Per entendre aquest comportament, hem de tornar a visitar la sessió de la WWDC Creeu visualitzacions personalitzades amb SwiftUI
i veure l’algorisme que expliquen.

Com que la pila ofereix una amplada de 150, primer ofereix la meitat d’aquest (75) al nen vermell. El marc del rectangle assumeix aquesta amplada, igual que el rectangle, i tot el subtítol té una amplada de 75 punts.

A continuació, la pila ofereix l’amplada restant (75) al nen verd. Com que té una amplada mínima de 100, la vista es fa de 100 punts d’amplada. El HStack
en si es fa ampli 75 + 100 = 175 punts.

Si intercanviem les dues subvistes, obtindrem exactament el mateix resultat, només dibuixat en un ordre diferent. Això es deu al fet que la pila organitza els seus fills segons la flexibilitat que tenen i els processa des del més petit fins al més flexible.

No obstant això, el significat de “menys flexible” no es defineix ni a la sessió de la WWDC ni a la documentació. Per entendre l’ordre de la flexibilitat, vam dedicar gran part del nostre temps a experimentar detingudament i vam fer el següent:

Del més petit al més flexible

  • Visualització de mida fixa

  • Vista d’amplada mínima i màxima

  • Veure només amb amplada màxima

  • Vista d’amplada mínima

Per a les visualitzacions amb la mateixa flexibilitat segons la llista anterior, hem hagut de tornar a ordenar en funció de l’amplada mínima o màxima. Ho vam intentar a fons i va resultar ser una bona intuïció, però no tota la veritat.

Per exemple, tingueu en compte la jerarquia següent:

								HStack(spacing: 0) {
    Rectangle().fill(Color.red).frame(maxWidth: 100).measure()
    Rectangle().fill(Color.green).frame(minWidth: 90, maxWidth: 200).measure()
}
.frame(width: 150, height: 100)

							

Segons la nostra classificació, el nen verd amb l’amplada mínima i màxima ha d’obtenir primer l’amplada de 75 proposada primer, convertint-se en l’amplada mínima de 90. Després, el nen vermell ha d’obtenir l’amplada restant de 60 acceptant aquesta amplada, perquè hi ha només límit màxim d’amplada 100.

No obstant això, el rectangle vermell té una amplada de 75. SwiftUI sembla ser la primera oferta al nen vermell. És evident que es tracta d’un error a SwiftUI o un error que entenem. (Spoiler: aquest és l’últim!).

La veritat de HStack
ordenar la vista sembla molt més senzill: la flexibilitat de la vista està determinada per l’amplada que es pot fer
.

A l’exemple anterior, el nen vermell pot arribar a tenir entre 0 i 100 punts d’amplada, per tant té una flexibilitat de 100. El nen verd pot arribar a tenir entre 90 i 200 punts d’amplada, per tant, té una flexibilitat de 110.

Això també explica per què la nostra heurística inicial, lleugerament excessivament complexa, funciona en la majoria dels casos:

  • la visualització de mida fixa té flexibilitat 0.

  • vista amb tots dos minWidth
    i maxWidth
    té la flexibilitat de maxWidth-minWidth
    .

  • veure només amb maxWidth
    té la flexibilitat de 0...maxWidth
    .

  • veure només amb minWidth
    té la flexibilitat de minWidth...CGFloat.someLargeNumber

La vista d’amplada mínima sempre serà l’última a la pràctica a causa de la flexibilitat de minWidth...CGFloat.someLargeNumber
és molt gran. Les visualitzacions de mida fixa sempre seran les primeres a causa de la seva flexibilitat de 0. Tot i això, en el nostre enfocament inicial es van barrejar les vistes d’amplada màxima i d’amplada mínima i màxima.

Nota: hem escrit CGFloat.someLargeNumber
en canvi CGFloat.greatestFiniteMagnitude
. El nombre ha de ser prou gran, però no prou gran com per perdre la precisió.

Vam estar a Swift Talk, la nostra sèrie de vídeos setmanals redirigint totes les parts importants del sistema de disseny SwiftUI
com una manera d’entendre completament el seu comportament, com sempre, primer episodi
de la sèrie és lliure de veure.

Al proper episodi, aplicarem exactament l’algoritme anterior per a HStacks, així que estigueu atents.

Per a aquells que prefereixen llegir, el nostre llibre Pensant a SwiftUI
inclou capítols per al disseny de la vista, inclòs l’algorisme de disseny i com es poden crear dissenys avançats.

Add a Comment

Your email address will not be published. Required fields are marked *