Layer é uma abstração de conteúdo gráfico que gerencia a representação visual dos elementos de interface em aplicações móveis. Ao contrário de UIView, layer não processa eventos de toque nem participa do Auto Layout — sua única função é renderização, animação e composição de pixels. De acordo com Apple QuartzCore Documentation, 2025, cada UIView em iOS tem um CALayer associado que realmente gerencia o desenho e a animação. Compreender a estrutura das camadas permite ao desenvolvedor controlar o desempenho da renderização ao nível de pixels individuais.
Principais conclusões
Layer é um objeto de baixo nível do sistema gráfico que armazena uma imagem bitmap de um fragmento de tela e gerencia seus atributos visuais: posição, tamanho, rotação, opacidade, sombra e cor. Em iOS, cada UIView tem um CALayer embutido acessível através da propriedade layer. Um desenvolvedor pode trabalhar diretamente com a camada, ignorando UIView, para um controle refinado da renderização.
A arquitetura de camadas segue o padrão Model-View-Controller, onde CALayer atua como o Modelo — armazena o estado das propriedades visuais. Core Animation é o Controlador que gerencia as transições de animação entre estados. View (UIView) é um invólucro opcional que adiciona manipulação de toque e participação em Auto Layout.
De acordo com Apple WWDC 2024, o pipeline de renderização moderno do iOS utiliza Metal para composição de camadas. Cada CALayer é renderizado num buffer separado, após o qual Core Animation compõe todos os buffers na imagem final, tendo em conta a opacidade e os modos de mistura.
Em Android, o análogo de camadas é View e Drawable de fundo, mas o trabalho direto com camadas gráficas está disponível através de Canvas e RenderNode no Android 10+. Compreender o conceito de camada é importante para otimizar a renderização em ambas as plataformas.
A principal diferença reside na área de responsabilidade. View lida com entrada do utilizador (toques, gestos), posicionamento (Auto Layout, frame) e ciclo de vida. Layer é exclusivamente responsável pela apresentação visual: renderização de conteúdo, animação de propriedades e composição com outras camadas.
Esta separação permite armazenar em cache a representação bitmap da camada independentemente da View. Se a camada não mudar, Core Animation utiliza o frame em cache sem chamar drawRect. Para elementos estáticos, isto proporciona um aumento significativo de desempenho sem alterações de código.
iOS fornece uma rica hierarquia de classes que herdam de CALayer. Cada subclasse é otimizada para um cenário específico: exibição de texto, gráficos vetoriais, gradientes ou transformações 3D. Escolher o tipo de camada correto afeta diretamente o desempenho da renderização.
Em Android, o conceito de camada é implementado através de RenderNode, ViewLayer e HardwareRenderer. A partir do Android 5.0 (API 21), cada View é renderizado na sua própria camada de aceleração por hardware, permitindo animações sem chamar onDraw.
Flexibilidade adicional em iOS é fornecida por CAReplicatorLayer e CAEmitterLayer. O primeiro é usado para criar padrões repetitivos, o segundo para sistemas de partículas. Ambos funcionam exclusivamente na GPU, permitindo criar efeitos visuais complexos sem perda de desempenho.
A hierarquia de camadas em iOS segue uma estrutura de árvore: cada CALayer pode conter múltiplas subcamadas filhas. Todas as transformações aplicadas à camada pai — escala, rotação, translação — são automaticamente aplicadas aos elementos filhos. Isto garante consistência visual durante as animações.
A composição da cena é realizada pelo Core Animation na seguinte ordem: primeiro o fundo é renderizado, depois cada camada filha por ordem de baixo para cima. Para cada camada, Core Animation verifica as propriedades de opacidade, máscaras e modos de mistura, depois compõe-nas no frame final.
De acordo com Apple Documentation, a composição de uma camada com opaque = true e sem canal alfa é feita sem passos adicionais — a GPU simplesmente copia pixels sobre a camada anterior. Se a camada tiver transparência, a GPU realiza mistura alfa, o que requer recursos computacionais adicionais.
Em Android, a composição de camadas é realizada através do SurfaceFlinger — um serviço de sistema que recebe buffers de cada aplicação e os compõe de acordo com a ordem z. Cada Window em Android é uma Surface separada que pode conter múltiplas camadas gráficas.
CALayer.mask — uma propriedade que permite aplicar uma máscara de forma arbitrária a uma camada. A máscara pode ser qualquer outro CALayer — por exemplo, CAShapeLayer com um caminho circular ou CAGradientLayer para criar uma transição suave de opacidade. Usar máscaras aumenta a carga da GPU, pois requer um passo de renderização adicional para calcular os valores alfa de cada pixel.
Para recorte retangular simples, recomenda-se usar cornerRadius e masksToBounds. Ao contrário de máscaras através da propriedade mask, cornerRadius é processado por hardware na fase de rasterização e não requer um passo adicional.
shouldRasterize é uma propriedade chave de CALayer para otimização de desempenho. Quando shouldRasterize é definido como true, Core Animation renderiza a camada e todas as suas subcamadas num buffer offscreen separado. Em frames subsequentes, a imagem bitmap em cache é usada em vez de re-renderizar.
O cache é eficaz para camadas estáticas ou que raramente mudam: sombras, gradientes, texto com cantos arredondados. No entanto, para camadas atualizadas frequentemente (animação, vídeo, rolagem), a rasterização pode degradar o desempenho, pois cada frame requer regeneração do cache.
De acordo com pesquisa da Objc.io, o uso adequado de shouldRasterize no iPad Pro reduz o tempo de renderização de um ecrã complexo de 25 ms para 8 ms — mais de três vezes. A condição chave é que a camada não deve mudar mais do que uma vez a cada 3–5 frames.
O primeiro exemplo demonstra a configuração de propriedades visuais básicas de CALayer em Swift — cantos arredondados, sombra e borda:
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
}
}
O segundo exemplo — criar uma animação de camada em Swift usando CABasicAnimation. A propriedade position é animada sem envolvimento 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")
O terceiro exemplo — trabalhar com RenderNode em Kotlin no Android. RenderNode é um análogo direto de CALayer, permitindo operar com camadas gráficas ao nível do 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
}
Perguntas frequentes
UIView é um invólucro em torno de CALayer que adiciona manipulação de toque e participação em Auto Layout. Layer apenas lida com renderização e animação. Pode trabalhar diretamente com CALayer, mas UIView é necessário para processar eventos de entrada.
shouldRasterize ativa o cache da camada num buffer offscreen separado. Use-o para elementos estáticos ou que raramente mudam com sombras ou composição complexa. Não use para camadas animadas frequentemente — a regeneração do cache será mais cara que a renderização direta.
Defina a propriedade cornerRadius para arredondar cantos e masksToBounds = true para recortar o conteúdo aos limites da camada. Para sombras, masksToBounds deve ser false, caso contrário a sombra será recortada — neste caso, use uma camada separada para a sombra.
Sim, RenderNode no Android 10+ fornece funcionalidade semelhante: gerir posição, escala, rotação e opacidade ao nível da camada gráfica. Canvas e HardwareRenderer fornecem renderização baseada em GPU. No entanto, arquiteturalmente Android não separa View e camada tão estritamente como iOS.
Uma sombra em CALayer é calculada através de shadowPath ou automaticamente com base no canal alfa. O cálculo automático requer percorrer todos os pixels da camada, o que é caro. Especifique um shadowPath explícito — um retângulo ou UIBezierPath — isto permite que a GPU calcule a sombra sem percorrer o conteúdo.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também