Layer — је апстракција графичког садржаја која управља визуелним приказом елемената интерфејса у мобилним апликацијама. За разлику од UIView, layer не обрађује догађаје додира и не учествује у Auto Layout — његов задатак је искључиво рендеровање, анимација и композиција пиксела. Према Apple QuartzCore Documentation, 2025, сваки UIView у iOS има повезани CALayer који заправо управља цртањем и анимацијом. Разумевање структуре слојева омогућава програмеру да контролише перформансе рендеровања на нивоу појединачних пиксела.
Главно
Layer — је нисконвони објекат графичког система који чува растерску слику фрагмента екрана и управља његовим визуелним атрибутима: положајем, величином, ротацијом, провидношћу, сенком и бојом. У iOS сваки UIView има уграђени CALayer, доступан путем својства layer. Програмер може радити директно са layer-ом, заобилазећи UIView, за фино подешавање рендеровања.
Архитектура слојева следи образац Model-View-Controller, где CALayer делује као Model — чува стање визуелних својстава. Core Animation је Controller који управља анимацијом прелаза између стања. View (UIView) — опционални омотач који додаје обраду додира и учешће у Auto Layout.
Према Apple WWDC 2024, савремени pipeline рендеровања iOS користи Metal за композицију слојева. Сваки CALayer се црта у посебан бафер, након чега Core Animation врши спајање свих бафера у коначну слику узимајући у обзир провидност и blending режиме.
У Android аналогон слојева су View и позадински Drawable, али директан рад са графичким слојевима је доступан кроз Canvas и RenderNode у Android 10+. Разумевање концепта layer је важно за оптимизацију рендеровања на обе платформе.
Главна разлика је у области одговорности. View одговара за кориснички унос (додир, гестови), позиционирање (Auto Layout, frame) и животни циклус. Layer одговара искључиво за визуелни приказ: рендеровање садржаја, анимацију својстава и композицију са другим слојевима.
Ово раздвајање омогућава кеширање растерске представе слоја независно од View. Ако се слој не мења, Core Animation користи кеширани кадар без позивања drawRect. За статичне елементе ово даје значајан пораст перформанси без промене кода.
iOS пружа богату хијерархију класа које наслеђују од CALayer. Свака подкласа је оптимизована за конкретан сценарио: приказ текста, векторске графике, градијената или 3D трансформација. Избор правилног типа слоја директно утиче на перформансе рендеровања.
У Android концепт слојева је имплементиран кроз RenderNode, ViewLayer и HardwareRenderer. Почевши од Android 5.0 (API 21), сваки View се рендерује у сопствени слој хардверског убрзања, што омогућава извођење анимација без позивања onDraw.
Додатну флексибилност у iOS пружају CAReplicatorLayer и CAEmitterLayer. Први се користи за креирање понављајућих образаца, други — за системе честица. Оба раде искључиво на GPU, што омогућава креирање сложених визуелних ефеката без губитка перформанси.
Хијерархија слојева у iOS се гради по принципу дрвета: сваки CALayer може садржати више подређених sublayer-а. Све трансформације примењене на родитељски слој — скала, ротација, померај — аутоматски се примењују на подређене елементе. Ово обезбеђује конзистентност визуелног приказа током анимација.
Композиција сцене се извршава од стране Core Animation следећим редоследом: прво се рендерује позадина (background), затим сваки подређени слој редом додавања одоздо према горе. За сваки слој Core Animation проверава својства провидности, маски и blending режима, након чега врши спајање (compositing) у коначни кадар.
Према Apple Documentation, композиција слоја са opaque = true и без алфа канала се извршава без додатних пролаза — GPU једноставно копира пикселе преко претходног слоја. Ако слој садржи провидност, GPU врши алфа-блендинг, што захтева додатне рачунске ресурсе.
У Android композиција слојева се врши путем SurfaceFlinger — системског сервиса који прима бафере од сваке апликације и спаја их узимајући у обзир z-редослед. Сваки Window у Android је посебан Surface који може садржати више графичких слојева.
CALayer.mask — својство које омогућава примену маске произвољног облика на слој. Маска може бити било који други CALayer — на пример, CAShapeLayer са кружним path или CAGradientLayer за стварање глатког прелаза провидности. Коришћење маски повећава оптерећење GPU, јер захтева додатни пролаз рендеровања за израчунавање алфа вредности сваког пиксела.
За једноставно обрезивање по правоугаоним границама препоручује се коришћење cornerRadius и masksToBounds. За разлику од маски преко својства mask, cornerRadius се обрађује хардверски у фази растеризације и не захтева додатни пролаз.
shouldRasterize — кључно својство CALayer за оптимизацију перформанси. Када је shouldRasterize постављен на true, Core Animation рендерује слој и све његове sublayer-е у посебан растерски бафер (offscreen buffer). При наредним кадровима, уместо поновног рендеровања, користи се кеширана растерска слика.
Кеширање је ефикасно за статичне или ретко променљиве слојеве: сенке, градијенте, текст са заобљеним угловима. Међутим, за често ажуриране слојеве (анимација, видео, скрол) растеризација може погоршати перформансе, јер сваки кадар захтева поновно генерисање кеша.
Према истраживању Objc.io, правилна употреба shouldRasterize на iPad Pro смањује време рендеровања сложеног екрана са 25 ms на 8 ms — више од три пута. Кључни услов: слој се не сме мењати чешће од једном у 3-5 кадрова.
Први пример демонстрира подешавање основних визуелних својстава CALayer у Swift — заобљавање углова, сенка и ивица:
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
}
}
Други пример — креирање анимације слоја у Swift коришћењем CABasicAnimation. Анимира се својство position без учешћа 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")
Трећи пример — рад са RenderNode у Kotlin на Android. RenderNode — директни аналогон CALayer, који омогућава рад са графичким слојевима на нивоу 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
}
Често постављана питања
UIView — је омотач око CALayer који додаје обраду додира и учешће у Auto Layout. Layer се бави само рендеровањем и анимацијом. Рад директно са CALayer је могућ, али за обраду улазних догађаја потребан је UIView.
shouldRasterize укључује кеширање слоја у посебан offscreen buffer. Користите за статичне или ретко променљиве елементе са сенкама или сложеном композицијом. Немојте користити за често анимиране слојеве — поновно генерисање кеша биће скупље од директног рендеровања.
Подесите својство cornerRadius за заобљавање углова и masksToBounds = true за обрезивање садржаја по границама слоја. За сенку masksToBounds мора бити false, иначе ће сенка бити обрезана — у овом случају користите посебан слој за сенку.
Да, RenderNode у Android 10+ пружа сличну функционалност: управљање положајем, размером, ротацијом и провидношћу на нивоу графичког слоја. Canvas и HardwareRenderer обезбеђују рендеровање путем GPU. Међутим, архитектонски Android не раздваја View и слој тако строго као iOS.
Сенка у CALayer се израчунава путем shadowPath или аутоматски на основу алфа канала. Аутоматско израчунавање захтева пролазак кроз све пикселе слоја, што је скупо. Наведите експлицитан shadowPath — правоугаоник или UIBezierPath — то ће омогућити GPU да израчуна сенку без прегледа садржаја.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође