web-dev-qa-db-fra.com

CALayers n'a pas été redimensionné lors de la modification des limites de UIView. Pourquoi?

J'ai un UIView qui a environ 8 sous-couches CALayer différentes ajoutées à son calque . Si je modifie les limites de la vue (animé), la vue elle-même est réduite (je l'ai vérifiée avec un backgroundColor), mais la taille des sous-couches reste inchangée .

Comment résoudre ceci?

88
Geri

J'ai utilisé la même approche que Solin, mais il y a une faute de frappe dans ce code. La méthode devrait être:

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

Pour mes besoins, j'ai toujours souhaité que la sous-couche ait la taille de la vue parent. Mettez cette méthode dans votre classe de vue.

129
Chadwick Wood

Étant donné que CALayer sur l'iPhone ne prend pas en charge les gestionnaires de disposition, je pense que vous devez transformer le calque principal de votre vue en une sous-classe CALayer personnalisée dans laquelle vous remplacez layoutSublayers pour définir les images de toutes les sous-couches. Vous devez également remplacer la méthode +layerClass de votre vue pour renvoyer la classe de votre nouvelle sous-classe CALayer.

24
Ole Begemann

Je l'ai utilisé dans UIView.

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

super.layoutSublayersOfLayer(layer)
}

Travaille pour moi.

11
Runo Sahara

J'ai eu le même problème. Dans la couche d'une vue personnalisée, j'ai ajouté deux sous-couches supplémentaires. Afin de redimensionner les sous-couches (chaque fois que les limites de la vue personnalisée changent), j'ai implémenté la méthode layoutSubviews de ma vue personnalisée; Dans cette méthode, je viens de mettre à jour le cadre de chaque sous-couche afin qu'il corresponde aux limites actuelles du calque de ma sous-vue.

Quelque chose comme ça:

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

Swift 3 Version  

Dans la cellule personnalisée, Ajouter les lignes suivantes 

Déclarer d'abord

let gradientLayer: CAGradientLayer = CAGradientLayer()

Puis ajoutez les lignes suivantes

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

2017

La réponse littérale à cette question:

"CALayers n'a pas été redimensionné lors de la modification de UIView. Pourquoi?"

est-ce pour le meilleur ou pour le pire

needsDisplayOnBoundsChange

la valeur par défaut est false dans CALayer.

solution,

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
    }
}

En effet, je vous dirige vers ce QA

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

ce qui explique, que diable fait le paramètre contentsScale critique; vous devez généralement également définir cela lorsque vous définissez needsDisplayOnBoundsChange.

3
Fattie

Comme [Ole] l'a écrit, CALayer ne prend pas en charge le redimensionnement automatique sur iOS. Donc, vous devez ajuster la mise en page manuellement. Mon option était d'ajuster le cadre de la couche dans (iOS 7 et versions antérieures)

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

ou (à partir de iOS 8)

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinato
0
DevGansta