ScrollView SwiftUI : du scroll basique aux carrousels avancés

Lors de l’arrivée de SwiftUI, le composant ScrollView était assez basique comparé à son équivalent UIKit.

À partir d’iOS 16, Apple a commencé à améliorer ce composant, avec des changements importants en iOS 17, puis consolidés en iOS 18. Nous allons passer en revue ces évolutions et ce qu’elles ont apporté.

iOS 16 : premières améliorations

iOS 16 introduit plusieurs fonctionnalités pour rendre le scroll plus flexible et l’expérience utilisateur plus naturelle :

  • refreshable() → Ajoute un pull-to-refresh natif
  • scrollIndicators() → Affiche ou masque les indicateurs de scroll (remplace le showsIndicators du constructeur de la ScrollView)
  • scrollDisabled() → Active ou désactive le scroll.
  • scrollDismissesKeyboard() → Cache le clavier lors du scroll, avec trois modes :
    • immediately → dès le début du scroll
    • interactively → progressivement
    • never → jamais
  • scrollBounceBehavior (iOS 16.4) → Configure le rebond du scroll, avec .basedOnSize pour désactiver le bounce si le contenu est trop petit et donc, non scrollable.

Ces améliorations sont notamment utiles pour les formulaires ou les listes dynamiques.

Exemple pratique : créer un carousel horizontal

Pour illustrer tous ces modifiers, passons sur un exemple complet d’un carousel horizontal avec snapping et suivi de la carte centrale, et un léger effet de scale lors du scroll.

iOS 18 : Observations plus fines

iOS 18 affine les fonctionnalités en ajoutant un contrôle dynamique sur la position et la visibilité des éléments, en permettant de remplacer totalement les PreferenceKey , les GeometryReader et certains usages des ScrollViewReader.

Nouveautés

  • onScrollPhaseChange() → Appelé à chaque transition de phase du scroll. Il fournit l’ancienne phase, la nouvelle phase, ainsi qu’un Context contenant notamment le contentOffset. Voici la liste des phases disponibles:
    • idle → Le scroll est complètement arrêté
    • tracking → L’utilisateur a posé le doigt
    • interacting → Le scroll manuel est actif
    • decelerating → L’utilisateur a lâché le doigt et le scroll passe en décélération
    • animating → Scroll déclenché programmatiquement
  • onScrollGeometryChange() → Appelé à chaque fois que le conteneur, le contenu ou le scroll offset de la ScrollView change. On a accès via un ScrollGeometry à beaucoup d’informations.
  • onScrollVisibilityChange() → Permet de savoir si un élément est visible.
  • onScrollTargetVisibilityChange() → Surveille la visibilité d’un élément via son id.

Ces APIs ouvrent la voie à des interactions plus poussées (animations synchronisées, tracking précis…)

Bonus iOS 26 : effets visuels

iOS 26 n’apporte aucune amélioration fonctionnelle au composant mais améliore l’expérience visuelle avec le style Liquid Glass.

Un nouveau modifier a donc fait son apparition:

  • scrollEdgeEffectStyle() → Définit l’effet visuel à appliquer lorsque le contenu scrollable passe en dessous de l’élément.
    • hard → Blur puissant et délimitation nette du composant
    • soft → Blur plus doux, sans séparation marquée

Ces effets s’appliquent sur les élément d’une Toolbar par exemple.

Conclusion

Apple a progressivement enrichi les ScrollView, qui sont aujourd’hui des composants matures, flexibles et ****parfaitement exploitables en production.

Les APIs disponibles sont claires et nous laissent une certaine liberté de personnalisation.

Et vous, jusqu’où avez-vous poussé l’utilisation des ScrollView dans vos projets SwiftUI ?

Nathan PORTE - Ingénieur études sénior