Layer es una abstracción de contenido gráfico que gestiona la representación visual de los elementos de la interfaz en aplicaciones móviles. A diferencia de UIView, layer no procesa eventos táctiles ni participa en Auto Layout — su única función es el renderizado, la animación y la composición de píxeles. Según Apple QuartzCore Documentation, 2025, cada UIView en iOS tiene un CALayer asociado que realmente gestiona el dibujo y la animación. Comprender la estructura de las capas permite al desarrollador controlar el rendimiento del renderizado a nivel de píxeles individuales.
Puntos clave
Layer es un objeto de bajo nivel del sistema gráfico que almacena una imagen de mapa de bits de un fragmento de pantalla y gestiona sus atributos visuales: posición, tamaño, rotación, opacidad, sombra y color. En iOS, cada UIView tiene un CALayer incorporado accesible a través de la propiedad layer. El desarrollador puede trabajar directamente con la capa, sin pasar por UIView, para un control detallado del renderizado.
La arquitectura de capas sigue el patrón Modelo-Vista-Controlador, donde CALayer actúa como el Modelo — almacena el estado de las propiedades visuales. Core Animation es el Controlador que gestiona las transiciones de animación entre estados. View (UIView) es un envoltorio opcional que añade manejo táctil y participación en Auto Layout.
Según Apple WWDC 2024, el pipeline de renderizado moderno de iOS utiliza Metal para la composición de capas. Cada CALayer se renderiza en un búfer separado, después de lo cual Core Animation compone todos los búferes en la imagen final, teniendo en cuenta la opacidad y los modos de mezcla.
En Android, el análogo de las capas son View y Drawable de fondo, pero el trabajo directo con capas gráficas está disponible a través de Canvas y RenderNode en Android 10+. Comprender el concepto de capa es importante para optimizar el renderizado en ambas plataformas.
La principal diferencia radica en el área de responsabilidad. View maneja la entrada del usuario (toques, gestos), el posicionamiento (Auto Layout, frame) y el ciclo de vida. Layer es exclusivamente responsable de la presentación visual: renderizado de contenido, animación de propiedades y composición con otras capas.
Esta separación permite almacenar en caché la representación de mapa de bits de la capa independientemente de la View. Si la capa no cambia, Core Animation utiliza el fotograma en caché sin llamar a drawRect. Para elementos estáticos, esto proporciona un aumento significativo del rendimiento sin cambios en el código.
iOS proporciona una rica jerarquía de clases que heredan de CALayer. Cada subclase está optimizada para un escenario específico: visualización de texto, gráficos vectoriales, degradados o transformaciones 3D. Elegir el tipo de capa correcto afecta directamente al rendimiento del renderizado.
En Android, el concepto de capa se implementa a través de RenderNode, ViewLayer y HardwareRenderer. A partir de Android 5.0 (API 21), cada View se renderiza en su propia capa de aceleración por hardware, permitiendo animaciones sin llamar a onDraw.
Flexibilidad adicional en iOS la proporcionan CAReplicatorLayer y CAEmitterLayer. El primero se utiliza para crear patrones repetitivos, el segundo para sistemas de partículas. Ambos funcionan exclusivamente en la GPU, permitiendo crear efectos visuales complejos sin pérdida de rendimiento.
La jerarquía de capas en iOS sigue una estructura de árbol: cada CALayer puede contener múltiples subcapas hijas. Todas las transformaciones aplicadas a la capa principal — escala, rotación, traslación — se aplican automáticamente a los elementos hijos. Esto garantiza la consistencia visual durante las animaciones.
La composición de la escena la realiza Core Animation en el siguiente orden: primero se renderiza el fondo, luego cada capa hija en orden de abajo hacia arriba. Para cada capa, Core Animation verifica las propiedades de opacidad, máscaras y modos de mezcla, y luego las compone en el fotograma final.
Según Apple Documentation, la composición de una capa con opaque = true y sin canal alfa se realiza sin pasos adicionales — la GPU simplemente copia píxeles sobre la capa anterior. Si la capa tiene transparencia, la GPU realiza la mezcla alfa, lo que requiere recursos computacionales adicionales.
En Android, la composición de capas se realiza a través de SurfaceFlinger — un servicio del sistema que recibe búferes de cada aplicación y los compone según el orden z. Cada Window en Android es una Surface separada que puede contener múltiples capas gráficas.
CALayer.mask — una propiedad que permite aplicar una máscara de forma arbitraria a una capa. La máscara puede ser cualquier otro CALayer — por ejemplo, CAShapeLayer con un path circular o CAGradientLayer para crear una transición suave de opacidad. El uso de máscaras aumenta la carga de la GPU, ya que requiere un paso de renderizado adicional para calcular los valores alfa de cada píxel.
Para recortes rectangulares simples, se recomienda usar cornerRadius y masksToBounds. A diferencia de las máscaras a través de la propiedad mask, cornerRadius se maneja por hardware en la etapa de rasterización y no requiere un paso adicional.
shouldRasterize es una propiedad clave de CALayer para la optimización del rendimiento. Cuando shouldRasterize se establece en true, Core Animation renderiza la capa y todas sus subcapas en un búfer fuera de pantalla separado. En fotogramas posteriores, se utiliza la imagen de mapa de bits en caché en lugar de volver a renderizar.
El almacenamiento en caché es efectivo para capas estáticas o que cambian raramente: sombras, degradados, texto con esquinas redondeadas. Sin embargo, para capas que se actualizan con frecuencia (animación, video, desplazamiento), la rasterización puede degradar el rendimiento, ya que cada fotograma requiere regenerar la caché.
Según una investigación de Objc.io, el uso adecuado de shouldRasterize en iPad Pro reduce el tiempo de renderizado de una pantalla compleja de 25 ms a 8 ms — más de tres veces. La condición clave es que la capa no debe cambiar más de una vez cada 3–5 fotogramas.
El primer ejemplo demuestra la configuración de propiedades visuales básicas de CALayer en Swift — esquinas redondeadas, sombra y borde:
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
}
}
El segundo ejemplo — crear una animación de capa en Swift usando CABasicAnimation. La propiedad position se anima sin intervención 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")
El tercer ejemplo — trabajar con RenderNode en Kotlin en Android. RenderNode es un análogo directo de CALayer, que permite operar con capas gráficas a nivel de 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
}
Preguntas frecuentes
UIView es un envoltorio alrededor de CALayer que añade manejo táctil y participación en Auto Layout. Layer solo maneja el renderizado y la animación. Puedes trabajar directamente con CALayer, pero UIView es necesario para manejar eventos de entrada.
shouldRasterize habilita el almacenamiento en caché de la capa en un búfer fuera de pantalla separado. Úsalo para elementos estáticos o que cambian raramente con sombras o composición compleja. No lo uses para capas animadas con frecuencia — la regeneración de la caché será más costosa que el renderizado directo.
Establece la propiedad cornerRadius para redondear las esquinas y masksToBounds = true para recortar el contenido a los límites de la capa. Para las sombras, masksToBounds debe ser false, de lo contrario la sombra se recortará — en este caso, usa una capa separada para la sombra.
Sí, RenderNode en Android 10+ proporciona funcionalidad similar: gestionar posición, escala, rotación y opacidad a nivel de capa gráfica. Canvas y HardwareRenderer proporcionan renderizado basado en GPU. Sin embargo, arquitectónicamente Android no separa View y capa tan estrictamente como iOS.
Una sombra en CALayer se calcula mediante shadowPath o automáticamente basándose en el canal alfa. El cálculo automático requiere recorrer todos los píxeles de la capa, lo cual es costoso. Especifica un shadowPath explícito — un rectángulo o UIBezierPath — esto permite que la GPU calcule la sombra sin recorrer el contenido.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también