2017-03-03 6 views
3

Ich habe ein interessantes Problem, aber ich bin mir nicht sicher, wie man es löst. Ich versuche, UIView mit einem @IBInspectable zu erweitern. Bei dieser Methode scheint der Eckenradius jedoch von der Standardseite der Nib-Dateien und nicht von der tatsächlichen Größe der Ansicht aus festgelegt zu sein.Rundschreiben UIView Nicht ein voller Kreis

Also, wenn in IB ich den "View as" auf iPhoneSE und Build für iPhoneSE einstellen, ist die Ansicht ein Kreis. Wenn ich jedoch für iPhone7 baue, sind die Ecken nicht vollständig zu einem Kreis gerundet. Umgekehrt, wenn ich "Ansicht als" auf iPhone7 und Build für iPhone7 setze, ist die Ansicht ein Kreis. Wenn ich jedoch für iPhoneSE baue, sind die Ecken übermäßig gerundet.

Bilder und Code unten:

Erweiterung

extension UIView { 

    @IBInspectable var cornerRadius:Double { 
     get { 
      return Double(layer.cornerRadius) 
     } 
     set { 
      layer.cornerRadius = CGFloat(newValue) 
      layer.masksToBounds = newValue > 0 
     } 
    } 

    @IBInspectable var circleView:Bool { 
     get { 
      return layer.cornerRadius == min(self.frame.width, self.frame.height)/CGFloat(2.0) ? true : false 
     } 
     set { 
      if newValue { 
       layer.cornerRadius = min(self.frame.width, self.frame.height)/CGFloat(2.0) 
       layer.masksToBounds = true 
      } 
      else{ 
       layer.cornerRadius = 0.0 
       layer.masksToBounds = false 
      } 
     } 
    } 

} 

"Als" gesetzt, wie iPhoneSE in IB

Gebaut für iPhoneSE

enter image description here

Build for iPhone 7

enter image description here

"Als" gesetzt, wie iPhone7

Build for iPhone SE

enter image description here

Build for iPhone 7

enter image description here

IB Einstellungen enter image description here enter image description here

+0

Können Sie bitte Screenshot von Auto-Layout-Einstellungen und Screenshot, wenn Sie Kreisförmige UIView in IB ausgewählt haben? –

+0

@SamuelTulach Diese oben für Sie hinzugefügt. – steventnorris

Antwort

2

Sie erhalten nur einen vollständigen Kreis, wenn Ihre Ansicht ein Quadrat ist.

Wenn Sie Ansicht sind ein Rechteck und Sie setzen cornerRadius mit einem Wert weniger als die Hälfte der kleinsten Dimension, erhalten Sie die zweite Ansicht und wenn es ein Wert größer als das ist, erhalten Sie die Raute.

Überprüfen Sie Ihre Einschränkungen, und Sie sollten die cornerRadius berechnen, nachdem die Ansicht das Layout in viewDidLayout beendet, so dass Sie die richtige Größe erhalten.

hier ein Spielplatz zeigt das ist (ich habe eine Animation zu zeigen, besser die Frage hinzugefügt):

import UIKit 
import PlaygroundSupport 

extension UIView 
{ 
    func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval) 
    { 
    let animation = CABasicAnimation(keyPath:"cornerRadius") 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    animation.fromValue = from 
    animation.toValue = to 
    animation.duration = duration 
    self.layer.add(animation, forKey: "cornerRadius") 
    self.layer.cornerRadius = to 
    } 
} 

let v = UIView(frame: CGRect(x: 0, y: 0, width: 350, height: 450)) 
PlaygroundPage.current.liveView = v 

let squareView = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100)) 
squareView.backgroundColor = .red 
squareView.layer.masksToBounds = true 
v.addSubview(squareView) 
var cornerRadius = CGFloat(0.5*min(squareView.frame.width, 
            squareView.frame.height)) 
squareView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 

let rectangleView = UIView(frame: CGRect(x: 10, y: 200, width: 100, height: 200)) 
rectangleView.backgroundColor = .blue 
rectangleView.layer.masksToBounds = true 
v.addSubview(rectangleView) 
cornerRadius = CGFloat(0.5*min(rectangleView.frame.width, 
            rectangleView.frame.height)) 
rectangleView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 

let diamondView = UIView(frame: CGRect(x: 200, y: 200, width: 100, height: 200)) 
diamondView.backgroundColor = .green 
diamondView.layer.masksToBounds = true 
v.addSubview(diamondView) 
cornerRadius = CGFloat(0.5*max(diamondView.frame.width, 
           diamondView.frame.height)) 
diamondView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 
als 185,5

Playground output

+0

Die Aussicht ist ein Quadrat. Das Problem scheint nicht die Rechtwinkligkeit zu sein, es scheint zu sein, wenn der Code zum Runden im Lebenszyklus ausgeführt wird. Es läuft vor den Einschränkungen, die die Ansicht vollständig auslegen, daher ist die Rundheit falsch. – steventnorris

+0

@steventnorris Weil du den 'cornerRadius' * nach * berechnen solltest, hat die Ansicht das Layout beendet (es ist in meiner Antwort). Eine schnelle Lösung besteht darin, die "UIView" abzuleiten und diese Methode zu implementieren. – FranMowinckel

+0

Ja. Das muss ich vielleicht tun. Ich habe versucht, dies so zu tun, dass es für alle UIViews gilt. Wenn ich eine Unterklasse finde, gibt es keine Möglichkeit, die Unterklasse erneut zu bilden. Sagen wir zum Beispiel, ich unterziehe UIView als MyRoundView. Nun, wenn ich ein UILabel möchte, muss ich entscheiden, ob ich UILabel ableiten und den Code oder die Unterklasse MyRoundView kopieren soll und nicht die Methoden und Parameter, die mit UILabel kommen. – steventnorris

0

Sie erwähnten Breite und Höhe, aber sie gehalten Breite Einschränkung als 350

+0

Das Problem ist nicht die Einschränkungen. Dies sollte für nicht statische Breiten-/Höhenbeschränkungen funktionieren, und es basiert nicht darauf, wo es im Lebenszyklus ausgeführt wird. Ich fange an zu denken. – steventnorris

0

Wenn Sie nicht auf viewDidLayout verschieben möchten, können Sie einfach den Trick machen, bevor Sie Ihren Eckenradius festlegen, indem Sie .layoutIfNeeded() hinzufügen.

yourCircleView.layoutIfNeeded() 
yourCircleView.layer.cornerRadius = yourCircleView.frame.size.width/2