Layer est une abstraction de contenu graphique qui gère la représentation visuelle des éléments d'interface dans les applications mobiles. Contrairement à UIView, layer ne traite pas les événements tactiles et ne participe pas à Auto Layout — sa seule fonction est le rendu, l'animation et la composition de pixels. D'après Apple QuartzCore Documentation, 2025, chaque UIView dans iOS a un CALayer associé qui gère réellement le dessin et l'animation. Comprendre la structure des couches permet au développeur de contrôler les performances de rendu au niveau de pixels individuels.
Points clés
Layer est un objet de bas niveau du système graphique qui stocke une image bitmap d'un fragment d'écran et gère ses attributs visuels : position, taille, rotation, opacité, ombre et couleur. Dans iOS, chaque UIView a un CALayer intégré accessible via la propriété layer. Un développeur peut travailler directement avec la couche, en contournant UIView, pour un contrôle précis du rendu.
L'architecture des couches suit le modèle Model-View-Controller, où CALayer agit comme le Modèle — il stocke l'état des propriétés visuelles. Core Animation est le Contrôleur qui gère les transitions d'animation entre les états. View (UIView) est un wrapper optionnel qui ajoute la gestion tactile et la participation à Auto Layout.
Selon Apple WWDC 2024, le pipeline de rendu moderne d'iOS utilise Metal pour la composition des couches. Chaque CALayer est rendu dans un tampon séparé, après quoi Core Animation compose tous les tampons dans l'image finale, en tenant compte de l'opacité et des modes de fusion.
Dans Android, l'analogue des couches est View et Drawable d'arrière-plan, mais le travail direct avec les couches graphiques est disponible via Canvas et RenderNode dans Android 10+. Comprendre le concept de couche est important pour optimiser le rendu sur les deux plateformes.
La principale différence réside dans le domaine de responsabilité. View gère les entrées utilisateur (touchers, gestes), le positionnement (Auto Layout, frame) et le cycle de vie. Layer est exclusivement responsable de la présentation visuelle : rendu du contenu, animation des propriétés et composition avec d'autres couches.
Cette séparation permet de mettre en cache la représentation bitmap de la couche indépendamment de la View. Si la couche ne change pas, Core Animation utilise l'image mise en cache sans appeler drawRect. Pour les éléments statiques, cela offre une augmentation significative des performances sans modification du code.
iOS fournit une riche hiérarchie de classes héritant de CALayer. Chaque sous-classe est optimisée pour un scénario spécifique : affichage de texte, graphiques vectoriels, dégradés ou transformations 3D. Le choix du bon type de couche affecte directement les performances de rendu.
Dans Android, le concept de couche est implémenté via RenderNode, ViewLayer et HardwareRenderer. À partir d'Android 5.0 (API 21), chaque View est rendue dans sa propre couche d'accélération matérielle, permettant des animations sans appeler onDraw.
Une flexibilité supplémentaire dans iOS est fournie par CAReplicatorLayer et CAEmitterLayer. Le premier est utilisé pour créer des motifs répétitifs, le second pour les systèmes de particules. Les deux fonctionnent exclusivement sur le GPU, permettant de créer des effets visuels complexes sans perte de performance.
La hiérarchie des couches dans iOS suit une structure arborescente : chaque CALayer peut contenir plusieurs sous-couches enfants. Toutes les transformations appliquées à la couche parent — échelle, rotation, translation — sont automatiquement appliquées aux éléments enfants. Cela garantit la cohérence visuelle pendant les animations.
La composition de la scène est effectuée par Core Animation dans l'ordre suivant : d'abord l'arrière-plan est rendu, puis chaque couche enfant dans l'ordre de bas en haut. Pour chaque couche, Core Animation vérifie les propriétés d'opacité, de masques et de modes de fusion, puis les compose dans l'image finale.
Selon Apple Documentation, la composition d'une couche avec opaque = true et sans canal alpha est effectuée sans passes supplémentaires — le GPU copie simplement les pixels sur la couche précédente. Si la couche a de la transparence, le GPU effectue un mélange alpha, ce qui nécessite des ressources de calcul supplémentaires.
Dans Android, la composition des couches est effectuée via SurfaceFlinger — un service système qui reçoit les tampons de chaque application et les compose selon l'ordre z. Chaque Window dans Android est une Surface séparée qui peut contenir plusieurs couches graphiques.
CALayer.mask — une propriété qui permet d'appliquer un masque de forme arbitraire à une couche. Le masque peut être n'importe quel autre CALayer — par exemple, CAShapeLayer avec un chemin circulaire ou CAGradientLayer pour créer une transition douce d'opacité. L'utilisation de masques augmente la charge du GPU car elle nécessite une passe de rendu supplémentaire pour calculer les valeurs alpha de chaque pixel.
Pour un découpage rectangulaire simple, il est recommandé d'utiliser cornerRadius et masksToBounds. Contrairement aux masques via la propriété mask, cornerRadius est traité par le matériel au stade de la rastérisation et ne nécessite pas de passe supplémentaire.
shouldRasterize est une propriété clé de CALayer pour l'optimisation des performances. Lorsque shouldRasterize est défini sur true, Core Animation rend la couche et toutes ses sous-couches dans un tampon hors écran séparé. Dans les images suivantes, l'image bitmap mise en cache est utilisée au lieu d'un nouveau rendu.
La mise en cache est efficace pour les couches statiques ou rarement modifiées : ombres, dégradés, texte avec coins arrondis. Cependant, pour les couches fréquemment mises à jour (animation, vidéo, défilement), la rastérisation peut dégrader les performances car chaque image nécessite une régénération du cache.
Selon une recherche de Objc.io, l'utilisation appropriée de shouldRasterize sur iPad Pro réduit le temps de rendu d'un écran complexe de 25 ms à 8 ms — plus de trois fois. La condition clé est que la couche ne doit pas changer plus d'une fois toutes les 3 à 5 images.
Le premier exemple montre la configuration des propriétés visuelles de base de CALayer en Swift — coins arrondis, ombre et bordure :
import UIKit
class StyledView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
layer.cornerRadius = 12
layer.masksToBounds = false
layer.shadowColor = UIColor.darkGray.cgColor
layer.shadowOpacity = 0.3
layer.shadowOffset = CGSize(width: 0, height: 4)
layer.shadowRadius = 8
}
}
Le deuxième exemple — création d'une animation de couche en Swift avec CABasicAnimation. La propriété position est animée sans intervention de UIView :
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = NSValue(cgPoint: CGPoint(x: 0, y: 0))
animation.toValue = NSValue(cgPoint: CGPoint(x: 150, y: 300))
animation.duration = 1.0
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
targetLayer.add(animation, forKey: "moveAnimation")
Le troisième exemple — travail avec RenderNode en Kotlin sur Android. RenderNode est un analogue direct de CALayer, permettant d'opérer avec des couches graphiques au niveau Canvas :
import android.graphics.renderer.RenderNode
fun createLayer(): RenderNode {
val node = RenderNode("customLayer")
node.setPosition(0, 0, 300, 200)
node.setScaleX(1.5f)
node.setScaleY(1.5f)
val canvas = node.beginRecording()
canvas.drawColor(android.graphics.Color.BLUE)
node.endRecording()
return node
}
Foire aux questions
UIView est un wrapper autour de CALayer qui ajoute la gestion tactile et la participation à Auto Layout. Layer ne gère que le rendu et l'animation. Vous pouvez travailler directement avec CALayer, mais UIView est nécessaire pour traiter les événements d'entrée.
shouldRasterize active la mise en cache de la couche dans un tampon hors écran séparé. Utilisez-le pour les éléments statiques ou rarement modifiés avec des ombres ou une composition complexe. Ne l'utilisez pas pour les couches fréquemment animées — la régénération du cache sera plus coûteuse que le rendu direct.
Définissez la propriété cornerRadius pour arrondir les coins et masksToBounds = true pour couper le contenu aux limites de la couche. Pour les ombres, masksToBounds doit être false, sinon l'ombre sera coupée — dans ce cas, utilisez une couche séparée pour l'ombre.
Oui, RenderNode dans Android 10+ offre des fonctionnalités similaires : gestion de la position, de l'échelle, de la rotation et de l'opacité au niveau de la couche graphique. Canvas et HardwareRenderer fournissent un rendu basé sur GPU. Cependant, architecturalement, Android ne sépare pas View et couche aussi strictement qu'iOS.
Une ombre dans CALayer est calculée via shadowPath ou automatiquement en fonction du canal alpha. Le calcul automatique nécessite de parcourir tous les pixels de la couche, ce qui est coûteux. Spécifiez un shadowPath explicite — un rectangle ou UIBezierPath — cela permet au GPU de calculer l'ombre sans parcourir le contenu.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi