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 виконує зведення всіх буферів у фінальне зображення з урахуванням прозорості та режимів змішування.
У Android аналогом шарів виступають View та фонові Drawable, але пряма робота з графічними шарами доступна через Canvas та RenderNode в Android 10+. Розуміння концепції шару важливе для оптимізації рендерингу на обох платформах.
Головна відмінність — у зоні відповідальності. 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 може містити безліч дочірніх sublayers. Всі трансформації, застосовані до батьківського шару — масштаб, поворот, зміщення — автоматично застосовуються до дочірніх елементів. Це забезпечує консистентність візуального представлення при анімаціях.
Композиція сцени виконується Core Animation у наступному порядку: спочатку рендериться задній план, потім кожен дочірній шар у порядку додавання від нижнього до верхнього. Для кожного шару Core Animation перевіряє властивості прозорості, масок та режимів змішування, після чого виконує зведення у фінальний кадр.
Згідно з 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 рендерить шар та всі його sublayers в окремий растровий буфер (offscreen buffer). При подальших кадрах замість повторного рендерингу використовується закешоване растрове зображення.
Кешування ефективне для статичних або рідко змінюваних шарів: тіней, градієнтів, тексту з закругленими кутами. Однак для шарів, що часто оновлюються (анімація, відео, скрол), растеризація може погіршити продуктивність, оскільки кожен кадр потребує перегенерації кешу.
За даними дослідження Objc.io, правильне використання shouldRasterize на iPad Pro знижує час рендерингу складного екрану з 25 мс до 8 мс — більш ніж утричі. Ключова умова: шар не повинен змінюватися частіше, ніж раз на 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також