Layer — este o abstractizare a conținutului grafic care gestionează reprezentarea vizuală a elementelor de interfață în aplicațiile mobile. Spre deosebire de UIView, layer nu procesează evenimente de atingere și nu participă la Auto Layout — sarcina sa este exclusiv randarea, animația și compoziția pixelilor. Conform Apple QuartzCore Documentation, 2025, fiecare UIView în iOS are un CALayer asociat, care de fapt gestionează desenarea și animația. Înțelegerea structurii straturilor permite dezvoltatorului să controleze performanța randării la nivel de pixeli individuali.
Principalul
Layer — este un obiect de nivel scăzut al sistemului grafic care stochează imaginea rasterizată a unui fragment de ecran și gestionează atributele sale vizuale: poziție, dimensiune, rotație, transparență, umbră și culoare. În iOS, fiecare UIView are un CALayer încorporat, accesibil prin proprietatea layer. Dezvoltatorul poate lucra direct cu layer, ocolind UIView, pentru reglarea fină a randării.
Arhitectura straturilor urmează modelul Model-View-Controller, unde CALayer acționează ca Model — stochează starea proprietăților vizuale. Core Animation este Controller-ul care gestionează animația tranziției între stări. View (UIView) — o învelitoare opțională care adaugă procesarea atingerilor și participarea în Auto Layout.
Conform Apple WWDC 2024, pipeline-ul modern de randare iOS folosește Metal pentru compoziția straturilor. Fiecare CALayer este desenat într-un buffer separat, după care Core Animation îmbină toate bufferele în imaginea finală ținând cont de transparență și modurile de blending.
În Android analogul straturilor sunt View și Drawable-urile de fundal, dar lucrul direct cu straturi grafice este disponibil prin Canvas și RenderNode în Android 10+. Înțelegerea conceptului de layer este importantă pentru optimizarea randării pe ambele platforme.
Diferența principală constă în zona de responsabilitate. View răspunde de intrarea utilizatorului (atingeri, gesturi), poziționare (Auto Layout, frame) și ciclul de viață. Layer răspunde exclusiv de reprezentarea vizuală: randarea conținutului, animația proprietăților și compoziția cu alte straturi.
Această separare permite cache-ul reprezentării rasterizate a stratului independent de View. Dacă stratul nu se modifică, Core Animation folosește cadrul din cache, fără a apela drawRect. Pentru elemente statice, aceasta oferă o creștere semnificativă a performanței fără modificări de cod.
iOS oferă o ierarhie bogată de clase care moștenesc din CALayer. Fiecare subclasă este optimizată pentru un scenariu specific: afișarea textului, graficii vectoriale, gradienturilor sau transformărilor 3D. Alegerea tipului corect de strat influențează direct performanța randării.
În Android conceptul de straturi este implementat prin RenderNode, ViewLayer și HardwareRenderer. Începând cu Android 5.0 (API 21), fiecare View este randat în propriul strat de accelerare hardware, permițând executarea animațiilor fără a apela onDraw.
Flexibilitate suplimentară în iOS este oferită de CAReplicatorLayer și CAEmitterLayer. Primul este folosit pentru crearea de modele repetitive, al doilea — pentru sisteme de particule. Ambele funcționează exclusiv pe GPU, permițând crearea de efecte vizuale complexe fără pierdere de performanță.
Ierarhia straturilor în iOS este construită pe principiul arborelui: fiecare CALayer poate conține multiple sublayere copil. Toate transformările aplicate stratului părinte — scară, rotație, deplasare — se aplică automat elementelor copil. Aceasta asigură consistența reprezentării vizuale în timpul animațiilor.
Compoziția scenei este realizată de Core Animation în următoarea ordine: mai întâi se randează fundalul (background), apoi fiecare strat copil în ordinea adăugării de jos în sus. Pentru fiecare strat, Core Animation verifică proprietățile de transparență, măști și moduri de blending, după care efectuează îmbinarea (compositing) în cadrul final.
Conform Apple Documentation, compoziția stratului cu opaque = true și fără canal alfa se realizează fără treceri suplimentare — GPU copiază pur și simplu pixelii peste stratul anterior. Dacă stratul conține transparență, GPU efectuează alfa-blending, ceea ce necesită resurse de calcul suplimentare.
În Android compoziția straturilor se realizează prin SurfaceFlinger — serviciul de sistem care primește buffere de la fiecare aplicație și le îmbină ținând cont de ordinea z. Fiecare Window în Android este un Surface separat care poate conține multiple straturi grafice.
CALayer.mask — proprietatea care permite aplicarea unei măști de formă arbitrară stratului. Masca poate fi orice alt CALayer — de exemplu, CAShapeLayer cu path circular sau CAGradientLayer pentru crearea unei tranziții line de transparență. Utilizarea măștilor crește încărcarea GPU, deoarece necesită o trecere suplimentară de randare pentru calcularea valorilor alfa ale fiecărui pixel.
Pentru tăierea simplă după limite dreptunghiulare se recomandă utilizarea cornerRadius și masksToBounds. Spre deosebire de măștile prin proprietatea mask, cornerRadius este procesat hardware la etapa de rasterizare și nu necesită o trecere suplimentară.
shouldRasterize — proprietatea cheie a CALayer pentru optimizarea performanței. Când shouldRasterize este setat pe true, Core Animation randează stratul și toate sublayer-ele sale într-un buffer raster separat (offscreen buffer). La cadrele următoare, în locul randării repetate, se folosește imaginea rasterizată din cache.
Cache-ul este eficient pentru straturi statice sau care se modifică rar: umbre, gradienturi, text cu colțuri rotunjite. Totuși, pentru straturi actualizate frecvent (animație, video, derulare), rasterizarea poate degrada performanța, deoarece fiecare cadru necesită regenerarea cache-ului.
Conform cercetării Objc.io, utilizarea corectă a shouldRasterize pe iPad Pro reduce timpul de randare a unui ecran complex de la 25 ms la 8 ms — de peste trei ori. Condiția cheie: stratul nu trebuie să se modifice mai des decât o dată la 3-5 cadre.
Primul exemplu demonstrează configurarea proprietăților vizuale de bază ale CALayer în Swift — rotunjirea colțurilor, umbra și marginea:
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
}
}
Al doilea exemplu — crearea unei animații de strat în Swift folosind CABasicAnimation. Proprietatea position este animată fără participarea 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")
Al treilea exemplu — lucrul cu RenderNode în Kotlin pe Android. RenderNode — analogul direct al CALayer, care permite operarea cu straturi grafice la nivelul 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
}
Întrebări frecvente
UIView — este o învelitoare peste CALayer care adaugă procesarea atingerilor și participarea în Auto Layout. Layer se ocupă doar de randare și animație. Lucrul direct cu CALayer este posibil, dar pentru procesarea evenimentelor de intrare este necesar UIView.
shouldRasterize activează cache-ul stratului într-un offscreen buffer separat. Folosiți pentru elemente statice sau care se modifică rar, cu umbre sau compoziție complexă. Nu folosiți pentru straturi animate frecvent — regenerarea cache-ului va fi mai costisitoare decât randarea directă.
Setați proprietatea cornerRadius pentru rotunjirea colțurilor și masksToBounds = true pentru tăierea conținutului la limitele stratului. Pentru umbră, masksToBounds trebuie să fie false, altfel umbra va fi tăiată — în acest caz, folosiți un strat separat pentru umbră.
Da, RenderNode în Android 10+ oferă funcționalitate similară: gestionarea poziției, scării, rotației și transparenței la nivelul stratului grafic. Canvas și HardwareRenderer asigură randarea prin GPU. Cu toate acestea, arhitectural Android nu separă View și stratul la fel de strict ca iOS.
Umbra în CALayer este calculată prin shadowPath sau automat pe baza canalului alfa. Calculul automat necesită parcurgerea tuturor pixelilor stratului, ceea ce este costisitor. Specificați un shadowPath explicit — dreptunghi sau UIBezierPath — aceasta va permite GPU să calculeze umbra fără a examina conținutul.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și