2016-05-27 12 views
0

Ich habe in letzter Zeit ein nerviges Problem erlebt.So erstellen Sie eine UIImageView-Erweiterung, die von ihr selbst gerundet wird

Angenommen, ich möchte ein Bild an mehreren Stellen in meiner Anwendung verwenden, und überall muss es abgerundet werden, um ein Kreis zu sein. Da ich möchte, dass mein Code sauber ist, denke ich, dass diese Funktionalität (von sich selbst zu runden) innerhalb der Klasse UIImageView erweitern sollte. Ich habe eine einfache Klasse erstellt, die Storyboard-Konstruktor überschreibt und ist verantwortlich für die Einstellung corner richtig:

class RoundedImageView: UIImageView { 


    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.layer.cornerRadius = self.frame.size.width/2 
     self.layer.borderColor = UIColor.redColor().CGColor 
     self.layer.borderWidth = 2 
     self.layer.masksToBounds = true 
    } 
} 

Für Einschränkungen wie

  • Breite: 100,
  • Höhe: 100

    Dies funktioniert offensichtlich, da der Frame nach dem Aufruf des Konstruktors nicht geändert wird (weil er im Storyboard die richtigen Dimensionen hat). Das Problem tritt auf, wenn zum Beispiel sehen die Zwänge wie folgt aus:

  • Breite gleich zu 0,5 Super des

  • Seitenverhältnis: 1: 1

weil die Rahmen Änderungen nach dem Konstruktor aufgerufen wird.

Was ich am Ende ist, etwas zu tun wie folgt aus:

override func viewDidLayoutSubviews(){ 
    super.viewDidLayoutSubviews() 
    myRoundedImageInstance.layer.cornerRadius = ... 
} 

in jedem View-Controller, der die Instanz dieser Klasse nach innen hat ... ... das funktioniert, weil der Rahmen nach der Neuberechnung imageView ändert Abmessungen, aber das ist hässlich, und das Vorhandensein der Klasse scheint in diesem Fall unnötig.

Ich habe versucht, Frame-Neuberechnung in DrawRect - funktioniert auch nicht. Irgendwelche Ideen?

+0

Warum verschieben Sie Ihren Rundungscode nicht auf 'RoundedImageView.layoutSubviews'? Eine weitere Möglichkeit besteht darin, die Ebenenmaske auf einen kreisförmigen Pfad zu setzen. – nielsbot

+0

Wow, wusste nicht über diese Methode (layoutSubviews) für Ansichten, keine Controller anzeigen. Soll ich bei dieser Methode super anrufen? Ihre Antwort löste das Problem übrigens. Danke vielmals! – Adams

+0

"Weil ich möchte, dass mein Code sauber ist, denke ich, dass diese Funktionalität (der Rundung selbst) in die Klasse eingefügt werden sollte, die UIImageView erweitert." Ich verstehe nicht warum. Warum bringst du die Funktionalität nicht in UIImage, d. H. Das Bild _itself_ schneidet sich selbst in einen Kreis? – matt

Antwort

1

Sie können Ihren Kreisaktualisierungscode in Ihre layoutSubviews-Methode verschieben.

6

Hier ist ein einfaches Beispiel, das IBDesignable ist (Sie können sehen, wie es in der Interface Builder aussehen)

@IBDesignable 
    class RoundedUIImageView: UIImageView { 
     @IBInspectable var round: Bool = true { 
      didSet { 
       self.clipsToBounds = true 
       self.layer.cornerRadius = self.frame.width/2 
       self.layer.borderWidth = 2.5 
       self.layer.borderColor = UIColor(rgba: "#D0D0D0").CGColor 
      } 
     } 
    } 

Sie können es komplizierter machen, da dies setzt voraus, dass die UIImageView ein Quadrat ist. Wenn nicht, wird es am Ende eine Ellipse sein. Sie könnten die Mindestgröße berechnen und dann auf diese Weise schneiden. Aber das ist die einfachste Form von dem, was Sie versuchen zu tun.

EDIT: Gleiche Idee, aber der Code ist raffinierter.

import UIKit 

@IBDesignable 
class RoundedUIImageView: UIImageView { 
    @IBInspectable var round: Bool = true { 
     didSet { self.setNeedsLayout() } 
    } 

    @IBInspectable var width: CGFloat = 2.5 { 
     didSet { self.setNeedsLayout() } 
    } 

    @IBInspectable var color: UIColor = UIColor(rgba: "#D0D0D0") { 
     didSet { self.setNeedsLayout() } 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 
     self.clipsToBounds = true 

     if round { 
      self.layer.cornerRadius = self.frame.width/2 
     } else { 
      self.layer.cornerRadius = 0 
     } 

     self.layer.borderWidth = self.width 
     self.layer.borderColor = self.color.CGColor 
    } 
} 

Es hat Standardeinstellungen, so kann alles konsistent sein. Aber es ist auch durch das Storyboard anpassbar.

+0

Es ist wirklich cool (das IBDesignable Zeug), das einzige Problem ist, dass es meine Frage nicht beantwortet. Es reagiert nicht nur auf Layoutänderungen (Berechnung von Rahmen aus Constraints), sondern verlangt auch, dass ich diesen Wert jedes Mal manuell setze, wenn ich die Klasse benutze (weil ich ihn standardmäßig auf true setze, wird didSet nicht aufgerufen - ich habe es überprüft) . Die richtige Antwort ist der erste Kommentar zu meiner Frage. – Adams

+0

Ich aktualisierte meine Antwort, um genauer zu sein für das, was ich erklären wollte. – SeanRobinson159