2017-02-02 6 views
1

ich eine benutzerdefinierte UIView wie so haben:Subview Custom UIView hat falsche x Rahmenposition

import UIKit 

class MainLogoAnimationView: UIView { 

    @IBOutlet var customView: UIView! 
    var turquoiseCircle: AnimationCircleView! 
    var redCircle: AnimationCircleView! 
    var blueCircle: AnimationCircleView! 


    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setup() 
    } 

    func setup() { 
     _ = Bundle.main.loadNibNamed("MainLogoAnimationView", owner: self, options: nil)?[0] as! UIView 
     self.addSubview(customView) 
     customView.frame = self.bounds 
     setupAnimation() 
    } 

    let initialWidthScaleFactor: CGFloat = 0.06 

    func setupAnimation() { 
     let circleWidth = frame.size.width*initialWidthScaleFactor 
     let yPos = frame.size.height/2 - circleWidth/2 
     turquoiseCircle = AnimationCircleView(frame: CGRect(x: 0, y: yPos, width: circleWidth, height: circleWidth)) 
     turquoiseCircle.circleColor = UIColor(red: 137/255.0, green: 203/255.0, blue: 225/255.0, alpha: 1.0).cgColor 
     turquoiseCircle.backgroundColor = UIColor.lightGray 
     addSubview(turquoiseCircle) 
     redCircle = AnimationCircleView(frame: CGRect(x: 100, y: yPos, width: circleWidth, height: circleWidth)) 
     addSubview(redCircle) 
     blueCircle = AnimationCircleView(frame: CGRect(x: 200, y: yPos, width: circleWidth, height: circleWidth)) 
     blueCircle.circleColor = UIColor(red: 93/255.0, green: 165/255.0, blue: 213/255.0, alpha: 1.0).cgColor 
     addSubview(blueCircle) 
    } 
} 

ich ein hellblau gefärbt UIView in Interface Builder erstellt und die obige Ansicht MainLogoAnimationView als Unterklasse gesetzt. Wenn ich die app betreibe ich diese:

enter image description here

Es dass der Rahmen für die turquoiseCircle scheint nicht an x = 0 gelegt worden, wie ich es eingestellt. Nicht sicher, was ich hier falsch mache. Liegt es daran, dass es platziert wird, bevor die MainLogoAnimationView vollständig initialisiert ist und falsch platziert wurde? Ich habe versucht, die Rahmen der Kreise in layoutSubviews() zu setzen und das machte auch keinen Unterschied. Ich scheine das Problem viel zu verstehen, weil die Ansichten fehl am Platz sind und ich denke, dass ich etwas Grundlegendes vermisse. Was mache ich falsch?

UPDATE:

import UIKit 

class MainLogoAnimationView: UIView { 

    @IBOutlet var customView: UIView! 
    var turquoiseCircle: AnimationCircleView! 
    var redCircle: AnimationCircleView! 
    var blueCircle: AnimationCircleView! 


    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setup() 
    } 

    func setup() { 
     _ = Bundle.main.loadNibNamed("MainLogoAnimationView", owner: self, options: nil)?[0] as! UIView 
     self.addSubview(customView) 
     customView.frame = self.bounds 
     setupAnimation() 
    } 

    let initialWidthScaleFactor: CGFloat = 0.2 


    func setupAnimation() { 
     blueCircle = AnimationCircleView() 
     blueCircle.translatesAutoresizingMaskIntoConstraints = false 
     blueCircle.backgroundColor = UIColor.lightGray 
     blueCircle.circleColor = UIColor.blue.cgColor 
     addSubview(blueCircle) 

     redCircle = AnimationCircleView() 
     redCircle.translatesAutoresizingMaskIntoConstraints = false 
     redCircle.backgroundColor = UIColor.lightGray 
     addSubview(redCircle) 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 
     let circleWidth = bounds.size.width*initialWidthScaleFactor 
     let yPos = frame.size.height/2 - circleWidth/2 
     blueCircle.frame = CGRect(x: 0, y: yPos, width: circleWidth, height: circleWidth) 
     redCircle.frame = CGRect(x: frame.size.width/2 - circleWidth/2, y: yPos, width: circleWidth, height: circleWidth) 
    } 
} 

und:

Import UIKit

class AnimationCircleView: UIView { 

    var circleColor = UIColor(red: 226/255.0, green: 131/255.0, blue: 125/255.0, alpha: 1.0).cgColor { 
     didSet { 
      shapeLayer.fillColor = circleColor 
     } 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     setup() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setup() 
    } 

    let shapeLayer = CAShapeLayer() 

    func setup() { 
     let circlePath = UIBezierPath(ovalIn: self.bounds) 
     shapeLayer.path = circlePath.cgPath 
     shapeLayer.fillColor = circleColor 
     shapeLayer.frame = self.bounds 
     layer.addSublayer(shapeLayer) 
    } 

} 

enter image description here

Antwort

1

Es ist definitiv der Fall, dass die Einrichtung in init self.frame/self.bounds Werte liefern wird was auch immer die Ansicht initialisiert d-Werte sind und nicht die richtigen endgültigen Werte, wenn sie in der Ansichtshierarchie angeordnet sind. Wahrscheinlich ist der beste Weg, um dies zu handhaben, wie Sie versucht haben, die Ansichten in init hinzuzufügen, und verwenden Sie die Eigenschaft, um einen Verweis auf sie zu halten (Sie tun dies bereits) und setzen Sie den Rahmen in -layoutSubviews().

Der Grund, warum es wahrscheinlich in -layoutSubviews() nicht funktionierte, ist für jede Ansicht nach der Erstellung müssen Sie .translatesAutoresizingMaskIntoConstraints = false aufrufen. Andernfalls erstellt das System bei programmgesteuerten Ansichten Einschränkungen für die Werte, wenn diese als Unteransicht hinzugefügt werden, wobei alle Einstellungen von Frames überschrieben werden. Versuchen Sie, das einzustellen und zu sehen, wie es geht.

BEARBEITEN: Um die Größe des CAShapeLayers zu ändern, anstatt als Sublayer hinzuzufügen (was eine manuelle Größenanpassung erfordern würde), da die AnimationCirleView-Ansicht spezialisiert ist, kann die Ansicht von CAShapeLayer unterstützt werden. Siehe die Antwort unter Overriding default layer type in UIView in swift

+0

Genau das versucht. Positionen sind immer noch falsch .. – KexAri

+0

Unabhängig davon, beide sind definitiv Probleme: 1) Werte von Rahmen/Größe/Grenzen in Init (mit Coder :) wird, was sie in Interface Builder und nicht ihre endgültigen Werte in der View-Hierarchie waren. 2) Sie müssen unbedingt .translateAutoresizingMaskIntoConstraints = false für alle programmatisch erzeugten Ansichten aufrufen oder das System fügt Einschränkungen hinzu, die fast definitiv nicht Ihren Vorstellungen entsprechen. Ohne diese beiden Probleme anzugehen, wird es sehr schwer sein zu sehen, welches weitere Problem auftreten könnte. Hoffe das hilft. –

+0

Hey, also habe ich es nochmal mit einem einfacheren Beispiel versucht. Nur zwei Kreise. Sie können das obige Update sehen^Die Kreise scheinen jetzt an der richtigen Position zu sein, aber der Kreis wird nicht mehr angezeigt. – KexAri

Verwandte Themen