web-dev-qa-db-ger.com

CALayers wurde bei der Änderung der Grenzen von UIView nicht angepasst. Warum?

Ich habe eine UIView, die ungefähr 8 verschiedene CALayer-Sublayer zu ihrer Ebene hinzugefügt hat . Wenn ich die Grenzen der Ansicht ändere (animiert), dann schrumpft die Ansicht selbst (ich habe sie mit einer backgroundColor überprüft), aber Die Größe der Sublayer bleibt unverändert .

Wie löse ich das?

88
Geri

Ich habe den gleichen Ansatz verwendet wie Solin, aber in diesem Code ist ein Tippfehler enthalten. Die Methode sollte sein:

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

Für meine Zwecke wollte ich, dass der Sublayer immer die volle Größe der übergeordneten Ansicht hat. Fügen Sie diese Methode in Ihre Ansichtsklasse ein.

129
Chadwick Wood

Da CALayer auf dem iPhone keine Layout-Manager unterstützt, denke ich, dass Sie die Hauptebene Ihrer Ansicht zu einer benutzerdefinierten CALayer-Unterklasse machen müssen, in der Sie layoutSublayers überschreiben, um die Frames aller Sublayer festzulegen. Sie müssen auch die +layerClass-Methode Ihrer Ansicht überschreiben, um die Klasse Ihrer neuen CALayer-Unterklasse zurückzugeben.

24
Ole Begemann

Ich habe dies in der UIView verwendet.

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

super.layoutSublayersOfLayer(layer)
}

Funktioniert bei mir.

11
Runo Sahara

Ich hatte das gleiche Problem. In der Ebene einer benutzerdefinierten Ansicht fügte ich zwei weitere Unterebenen hinzu. Um die Größe der untergeordneten Layer zu ändern (wenn sich die Grenzen der benutzerdefinierten Ansicht ändern), habe ich die Methode layoutSubviews meiner benutzerdefinierten Ansicht implementiert. Innerhalb dieser Methode aktualisiere ich einfach den Frame jedes Sublayers, um ihn an die aktuellen Grenzen der Ebene meiner Subansicht anzupassen.

Etwas wie das:

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

Fügen Sie in der benutzerdefinierten Zelle folgende Zeilen hinzu 

Zuerst deklarieren

let gradientLayer: CAGradientLayer = CAGradientLayer()

Fügen Sie dann folgende Zeilen hinzu

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

2017

Die wörtliche Antwort auf diese Frage:

"CALayers wurde nicht an der UIView-Änderung der Größe angepasst. Warum?"

ist das besser oder schlechter

needsDisplayOnBoundsChange

der Standardwert ist in CALayer auf false gesetzt.

lösung,

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

In der Tat leite ich Sie zu dieser Qualitätssicherung

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

was erklärt, was zum Teufel die kritische Einstellung contentsScale macht; Sie müssen das normalerweise gleich einstellen, wenn Sie needsDisplayOnBoundsChange einstellen.

3
Fattie

Wie [Ole] schrieb, unterstützt CALayer keine Autoresizing-Funktion für iOS. Sie sollten also das Layout manuell anpassen. Meine Option bestand darin, den Rahmen der Ebene innerhalb von iOS 7 und früheren Versionen anzupassen.

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

oder (ab iOS 8)

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