Layouts en SwiftUI
Introduction aux Layouts
Dans SwiftUI, le concept de layout se réfère au protocole utilisé pour organiser les interfaces utilisateurs. Les layouts définissent la manière dont les différentes vues sont disposées les unes par rapport aux autres. Il est possible de créer des layouts personnalisés ainsi que des layouts conditionnels. De plus, il existe des layouts intégrés qui peuvent être utilisés lors de la création de layouts conditionnels.
Création de Layouts Personnalisés
Les layouts personnalisés sont utiles lorsque les layouts et vues intégrés ne répondent pas aux besoins spécifiques d'une application. Pour définir un layout personnalisé, vous devez implanter les méthodes ".sizeThatFits()" et ".placeSubviews()", qui sont obligatoires pour se conformer au protocole Layout :
struct MyCustomLayout: Layout {
func sizeThatFits(
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Void
) -> CGSize {
// Code personnalisé pour calculer et retourner la taille du conteneur du layout.
}
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Void
) {
// Code personnalisé pour disposer les sous-vues.
}
}
Utilisation de Layouts Personnalisés
Les layouts personnalisés peuvent être utilisés de la même manière que d'autres conteneurs de vues, tels que HStack. Pour les utiliser, il vous suffit d'inclure les vues entre accolades après le nom du layout :
MyCustomLayout {
// Ajoutez vos vues ici.
}
Exemple de Layout Personnalisé
Voici un exemple de layout personnalisé appelé "SpiralLayout" qui organise ses vues en spirale :
struct SpiralLayout: Layout {
func sizeThatFits(
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Void
) -> CGSize {
// Utiliser tout l'espace disponible.
proposal.replacingUnspecifiedDimensions()
}
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Void
) {
// Déterminer le rayon pour s'adapter à l'espace disponible.
let radius = min(bounds.size.width, bounds.size.height) / 2.0
// Calculer l'angle pour chaque vue, selon le nombre total de vues.
let angle = Angle.degrees(360.0 / Double(subviews.count)).radians
// Disposer chaque vue autour du centre de l'espace avec un rayon décroissant pour créer un effet de spirale.
for (index, subview) in subviews.enumerated() {
var place = CGPoint(x: 0, y: -radius * CGFloat(Float(index)) / 10)
.applying(CGAffineTransform(
rotationAngle: angle * Double(index)
))
place.x += bounds.midX
place.y += bounds.midY
subview.place(at: place, anchor: .center, proposal: .unspecified)
}
}
}
Layouts Conditionnels
Les layouts conditionnels peuvent changer dynamiquement. Par exemple, si l'espace disponible diminue, il est possible de passer automatiquement à un layout plus concis. Voici comment déclencher la création d'un layout conditionnel :
// Déclaration d'une variable qui renvoie un layout spécifique.
// Si une condition est vraie, un layout est retourné, sinon un autre layout est fourni.
let MyLayout = myCondition ? AnyLayout(SomeLayout()) : AnyLayout(AnotherLayout())
MyLayout {
// Ajoutez les sous-vues ici.
}
Exemple de Layout Conditionnel
Dans cet exemple, la variable "isVertical" détermine l'utilisation d'un "VStack" ou d'un "HStack", en fonction de la valeur de la variable :
@State private var isVertical = false
var body: some View {
let layout = isVertical ? AnyLayout(VStack()) : AnyLayout(HStack())
VStack {
Toggle("Switch to Vertical", isOn: $isVertical.animation()).font(.title2)
Spacer()
layout {
ForEach(0..<6) { i in
RoundedRectangle(cornerRadius: 5)
.fill(Color.green)
.frame(width: 50, height: 50)
}
}
}
.padding()
}
Conclusion
Les layouts en SwiftUI offrent une flexibilité incroyable pour créer des interfaces utilisateurs adaptées à diverses conditions et besoins. En maîtrisant les concepts de layouts personnalisés et conditionnels, les développeurs peuvent concevoir des applications plus élégantes et réactives.