Los CALayers no fueron redimensionados en el cambio de límites de UIView. ¿Por qué?

Tengo una UIView que tiene aproximadamente 8 subcapas CALayer diferentes agregadas a su capa. Si modifico los límites de la vista (animados), la vista misma se encoge (lo compruebo con un backgroundColor ), pero el tamaño de las subcapas permanece sin cambios .

¿Cómo resolver esto?

Usé el mismo enfoque que Solin usó, pero hay un error tipográfico en ese código. El método debería ser:

 - (void)layoutSubviews { // resize your layers based on the view's new bounds mylayer.frame = self.bounds; } 

Para mis propósitos, siempre quise que la subcapa fuera del tamaño completo de la vista principal. Pon ese método en tu clase de vista.

Como CALayer en el iPhone no es compatible con los administradores de diseño, creo que debe hacer que la capa principal de su vista sea una subclase de CALayer personalizada en la que sobrescriba las layoutSublayers de layoutSublayers para establecer los marcos de todas las subcapas. También debe anular el método +layerClass su vista para devolver la clase de su nueva subclase CALayer.

Usé esto en UIView.

 -(void)layoutSublayersOfLayer:(CALayer *)layer { if (layer == self.layer) { _anySubLayer.frame = layer.bounds; } super.layoutSublayersOfLayer(layer) } 

Funciona para mi.

Yo tuve el mismo problema. En la capa de una vista personalizada agregué dos subcapas más. Para cambiar el tamaño de las subcapas (cada vez que cambian los límites de la vista personalizada), implementé el método layoutSubviews de mi vista personalizada; Dentro de este método, simplemente actualizo el cuadro de cada subcapa para que coincida con los límites actuales de la capa de mi subvista.

Algo como esto:

 -(void)layoutSubviews{ //keep the same origin, just update the width and height if(sublayer1!=nil){ sublayer1.frame = self.layer.bounds; } } 

Versión de Swift 3

En la celda personalizada, agregue las siguientes líneas

Declarar primero

 let gradientLayer: CAGradientLayer = CAGradientLayer() 

Luego agrega las siguientes líneas

 override func layoutSubviews() { gradientLayer.frame = self.YourCustomView.bounds } 

2017

La respuesta literal a esta pregunta:

“Los CALayers no fueron redimensionados en el cambio de límites de UIView. ¿Por qué?”

es eso para bien o para mal

needsDisplayOnBoundsChange

por defecto es falso en CALayer .

solución,

 class CircularGradientViewLayer: CALayer { override init() { super.init() needsDisplayOnBoundsChange = true } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override open func draw(in ctx: CGContext) { go crazy drawing in .bounds } } 

De hecho, te dirijo a este QA

https://stackoverflow.com/a/47760444/294884

lo que explica, qué demonios hace la configuración critical contentsScale ; por lo general, debe establecerlo igualmente cuando configure needsDisplayOnBoundsChange.

Como [Ole] escribió, CALayer no admite la conversión automática en iOS. Por lo tanto, debe ajustar el diseño manualmente. Mi opción era ajustar el marco de la capa dentro (iOS 7 y anteriores)

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

o (a partir de iOS 8)

 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinato