iphone - ver - Los CALayers no fueron redimensionados en el cambio de límites de UIView. ¿Por qué?
itunes (7)
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?
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://.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 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.
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 <UIViewControllerTransitionCoordinator>)coordinato
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.
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
}