paint-brush
Un guide essentiel de SwiftUI : interface utilisateur réutilisable avec des modificateurs personnaliséspar@nemi
1,596 lectures
1,596 lectures

Un guide essentiel de SwiftUI : interface utilisateur réutilisable avec des modificateurs personnalisés

par Nemi Shah9m2023/04/28
Read on Terminal Reader

Trop long; Pour lire

Les ViewModifiers personnalisés dans SwiftUI vous permettent de créer des styles réutilisables pouvant être appliqués à toutes vos vues. Dans cet article, nous couvrirons des exemples de la façon dont cette fonctionnalité peut être utilisée pour rendre la création de l'interface utilisateur beaucoup plus facile. Le but de cet article est de couvrir certaines des différentes façons de créer des modificateurs et des styles personnalisés dans Swift UI.
featured image - Un guide essentiel de SwiftUI : interface utilisateur réutilisable avec des modificateurs personnalisés
Nemi Shah HackerNoon profile picture
0-item
1-item

La possibilité de créer des modificateurs de vue personnalisés est une fonctionnalité puissante de SwiftUI. Dans cet article, nous couvrirons des exemples de la façon dont cette fonctionnalité peut être utilisée pour rendre la création de l'interface utilisateur beaucoup plus facile. Si vous n'êtes pas familier avec les ViewModifiers dans SwiftUI et comment en créer des personnalisés, vous pouvez en savoir plus ici


Le but de cet article est de couvrir certaines des différentes façons de créer des modificateurs et des styles personnalisés dans SwiftUI et comment ils peuvent être utilisés pour rendre la construction de l'interface utilisateur plus déclarative tout en obtenant une sortie finale propre et cohérente.


L'interface utilisateur finale que nous voulons créer est la suivante :


Considérons tous les composants individuels à l'écran :

  • Image : un composant d'image standard avec un certain rayon d'angle
  • Textes : Nous avons un titre et un corps de texte
  • Bouton : un bouton pleine largeur

Code SwiftUI simple

Si vous créez cet écran sans aucun modificateur, le code ressemblera à ceci :


 struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .resizable() .aspectRatio(contentMode: .fill) .frame(minWidth: 0, maxWidth: .infinity) .frame(height: 220) .cornerRadius(12) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) Spacer() Button(action: { }) { Text("Label") .font(.system(size: 14, weight: .medium)) } .frame(minWidth: 0, maxWidth: .infinity) .padding(.horizontal, 10) .padding(.vertical, 12) .background(Color.blue) .foregroundColor(Color.white) .cornerRadius(12) } .padding(.all, 16) } }


Il y a quelques problèmes avec cette approche :

  • Le style de certains éléments (le texte du titre et des détails par exemple) devrait être dupliqué

  • Des modifications à certains des styles courants (remplissage d'élément, rayon d'angle, etc.) devraient être apportées à plusieurs endroits


Maintenant, vous pouvez résoudre ce problème à la manière UIKit en créant des vues personnalisées, mais je ne suis pas fan de cette approche car elle impliquait de s'éloigner des vues intégrées et rend l'intégration de nouveaux membres de l'équipe plus frictionnelle. Un moyen plus simple serait de définir des modificateurs de vue universels pouvant être appliqués à la place des styles eux-mêmes.


Décomposons le style commun dont nous avons besoin :

  • Conteneur d'écran : l'écran lui-même a un rembourrage universel, ceci est facultatif mais je préfère que tous les écrans aient un style universel
  • Rayon d'angle
  • Titre et corps du texte
  • Pleine largeur : les éléments doivent pouvoir remplir la largeur de leur parent (le bouton et l'image dans l'exemple ci-dessus)
  • Style de bouton
  • Mise à l'échelle des images

Modificateurs d'affichage personnalisés

Commençons par le rayon du coin :

 struct CommonCornerRadius: ViewModifier { func body(content: Content) -> some View { content .cornerRadius(12) } }


Celui-ci est assez simple, il nous permet d'appliquer un rayon de coin universel pour les éléments. Cela facilite la modification globale des styles d'application sans avoir à créer des vues personnalisées ou à effectuer plusieurs modifications dans la base de code.


 struct FullWidthModifier: ViewModifier { func body(content: Content) -> some View { content .frame(minWidth: 0, maxWidth: .infinity) } }


Celui-ci facilite la mise en œuvre des vues pleine largeur, plus besoin d'ajouter manuellement .frame !


 struct TitleTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) } } struct BodyTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) } }


Cela permettra un style de texte commun, normalement vous créerez des composants de texte personnalisés ou des fonctions utilitaires et ajouterez des composants d'interface utilisateur via le code.


 extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }


D'accord, vous m'avez compris… ce n'est pas un modificateur de vue personnalisé mais une simple extension. En effet, ViewModifiers s'applique aux vues génériques et certaines fonctions telles que resizable ne s'appliquent qu'aux images, l'utilisation d'une combinaison d'extensions et de modificateurs personnalisés permet de contourner ce problème.


 struct FullWidthButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .fullWidth() .foregroundColor(Color.white) .font(.system(size: 14, weight: .medium)) .padding(.horizontal, 10) .padding(.vertical, 12) .background(configuration.isPressed ? Color.blue.opacity(0.2) : Color.blue) } } struct FullWidthButton: ViewModifier { func body(content: Content) -> some View { content .buttonStyle(FullWidthButtonStyle()) } }


Enfin, c'est pour le bouton, notez que même si nous aurions pu simplement créer un ViewModifier pour obtenir le même effet, l'apparence du bouton n'aurait pas changé lorsqu'il aurait été tapé. En effet, la définition de .background sur un bouton l'oblige à utiliser cet arrière-plan dans les états activé et non activé. ButtonStyle nous permet de modifier l'opacité du bouton selon qu'il est enfoncé ou non.


Maintenant, pour plus de commodité, j'aime créer des extensions qui utilisent ces modificateurs :


 extension View { func commonCornerRadius() -> some View { modifier(CommonCornerRadius()) } func fullWidth() -> some View { modifier(FullWidthModifier()) } func title() -> some View { modifier(TitleTextModifier()) } func body() -> some View { modifier(BodyTextModifier()) } func fullWidthButton() -> some View { modifier(FullWidthButton()) } } extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }


Convertissons maintenant le code pour les utiliser au lieu de les styliser directement :


 struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .aspectFill() .fullWidth() .frame(height: 220) .commonCornerRadius() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .title() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .body() Spacer() Button(action: { }) { Text("Awesome") } .fullWidthButton() .commonCornerRadius() } .padding(.all, 16) } }


Beaucoup plus propre ! Maintenant, à première vue, cela ressemble à plus de code et d'efforts que de simplement définir manuellement les styles, mais à long terme, cela économisera beaucoup d'efforts. Personnellement, cette approche encourage également le style de votre application à être plus cohérent en s'appuyant davantage sur des modificateurs courants que sur une base de style vue par vue.


Et c'est tout ! Espérons que cela vous aide à créer vos applications plus rapidement et plus facilement, un autre avantage est que ces modificateurs peuvent être déposés dans n'importe laquelle de vos applications et modifiés pour correspondre à ses directives de style. J'ai également travaillé sur une bibliothèque pour aller encore plus loin, vous pouvez la consulter ici (PS : Au moment d'écrire ces lignes, la bibliothèque est à un stade très précoce, le référentiel est vide : p mais restez à l'écoute)


Également publié ici.