So zeichnen Sie eine benutzerdefinierte UIView, die nur ein Kreis ist - iPhone App

129

Wie würde ich ein benutzerdefiniertes UIView zeichnen, das buchstäblich nur eine Kugel (ein 2D-Kreis) ist? Würde ich einfach die drawRect-Methode überschreiben? Und kann mir jemand den Code zum Zeichnen eines blauen Kreises zeigen?

Wäre es auch in Ordnung, den Rahmen dieser Ansicht innerhalb der Klasse selbst zu ändern? Oder muss ich den Rahmen einer anderen Klasse ändern?

(Ich versuche nur, einen Ball aufzustellen, der herumspringt.)

StanLe
quelle

Antworten:

209

Sie könnten QuartzCore verwenden und etwas tun -

self.circleView = [[UIView alloc] initWithFrame:CGRectMake(10,20,100,100)];
self.circleView.alpha = 0.5;
self.circleView.layer.cornerRadius = 50;  // half the width/height
self.circleView.backgroundColor = [UIColor blueColor];
Kal
quelle
104
Zu Ihrer Information, damit Ihre Ansicht mit QuartCore ein Kreis ist, muss Ihr Eckenradius die Hälfte Ihrer Rahmenhöhe / -breite betragen. Dies ist der einfachste Weg, einen Kreis zu bilden, aber nicht unbedingt der effizienteste. Wenn die Leistung von entscheidender Bedeutung ist, liefert drawRect wahrscheinlich bessere Ergebnisse.
Benjamin Mayo
4
Und es ist. 100 ist die Höhe / Breite.
Kal
3
Ja, tut mir leid, dass ich das nicht auf dich gerichtet habe, Kal. Ich habe das StanLe gegenüber erwähnt, falls er Ansichten unterschiedlicher Größe verwenden möchte.
Benjamin Mayo
Wenn Ihre CircleView-Größe nicht 100X100 ist, sollte der CornerRadius die (neue Größe) / 2
Gran33
Aber ich habe bemerkt, dass der Kreis mit dem Eckradius manchmal leicht "flache" / abgeschnittene Kanten hat. Zumindest bei Verwendung mit einem Rand. Irgendeine Idee warum? Der Radius ist genau halb so groß wie die Ansicht. Ich dachte, es könnte ein Clipping-Problem sein, aber es scheint nicht so, selbst mit einer kleineren Unterschicht versucht - habe immer noch den gleichen Effekt.
Ixx
135

Würde ich einfach die drawRect-Methode überschreiben?

Ja:

- (void)drawRect:(CGRect)rect
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(ctx, rect);
    CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
    CGContextFillPath(ctx);
}

Wäre es auch in Ordnung, den Rahmen dieser Ansicht innerhalb der Klasse selbst zu ändern?

Im Idealfall nicht, aber Sie könnten.

Oder muss ich den Rahmen einer anderen Klasse ändern?

Ich würde die Eltern das kontrollieren lassen.

Steve
quelle
1
Wie kann ich benutzerdefinierte Farben einstellen, nicht nur Blau? Ich versuche, Weiß und Blau wie folgt zu verwenden: ([self.colorOfCircle CGColor]), aber es passiert nichts: \
gaussblurinc
@loldop ist self.colorOfCircle eine UIColor? Ist es eingestellt? Wenn Sie einen Haltepunkt in diese Zeile setzen und den Wert betrachten, ist es das, was Sie erwarten? Wenn Sie dies nachträglich festlegen, müssen Sie den Teil Ihrer Ansicht, der den Kreis enthält, ungültig machen.
Steve
9
@gaussblurinc verwenden CGContextSetFillColorWithColor(ctx, self.colorOfCircle.CGColor);, funktioniert die in der Lösung vorgeschlagene Methode CGColorGetComponentsnur mit einigen Farben, siehe stackoverflow.com/questions/9238743/…
yonilevy
Hinweis für alle, die sich daran festhalten. Eher, alsrect versehentlich self.framefür die Ellipse zu verwenden. Der richtige Wert ist self.bounds. D'oh! :)
Olie
31

Hier ist eine andere Möglichkeit, UIBezierPath zu verwenden (möglicherweise ist es zu spät ^^). Erstellen Sie einen Kreis und maskieren Sie UIView damit wie folgt:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
view.backgroundColor = [UIColor blueColor];

CAShapeLayer *shape = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:view.center radius:(view.bounds.size.width / 2) startAngle:0 endAngle:(2 * M_PI) clockwise:YES];
shape.path = path.CGPath;
view.layer.mask = shape;
Gintama
quelle
1
Es ist nicht wirklich notwendig, diese Formebene zu einer Maske zu machen. Sie können die Formebene einfach direkt als Ebene der Ansicht verwenden und ihr eine Füllfarbe geben. Die Maske ist wahrscheinlich deutlich teurer.
Jesse Rusak
Die Ebene von UIView ist CALayer. Wie können wir also eine Form auf dieser Ebene zeichnen? Ich nehme an, wir fügen der Ebene der Ansicht eine Formebene hinzu, ohne sie zu maskieren.
Gintama
1
Sie können UIView in Unterklassen unterteilen und die layerClassKlassenmethode überschreiben , um sie zu einer Formebene zu machen.
Jesse Rusak
@ JesseRusak, das Problem, das ich mit Ihrem Vorschlag habe (um die Form auf der Ebene von UIView selbst festzulegen), ist, dass Sie die Hintergrundfarbe nicht richtig verwenden müssen. Sie müssten eine fillColor anwenden und die backgroundColor auf clearColor setzen, was bedeutet, dass ein Benutzer der UIView die backgroundColor nicht auf natürliche Weise einstellen kann.
Richard Venable
25

Mein Beitrag mit einer Swift-Erweiterung:

extension UIView {
    func asCircle() {
        self.layer.cornerRadius = self.frame.width / 2;
        self.layer.masksToBounds = true
    }
}

Ruf einfach an myView.asCircle()

Kevin ABRIOUX
quelle
Die Einstellung masksToBoundsauf true und using selfist in dieser Antwort optional, aber es ist immer noch die kürzeste und beste Lösung
Max Desiatov,
17

Swift 3 - benutzerdefinierte Klasse, einfach wiederzuverwenden. Es verwendet backgroundColorset in UI Builder

import UIKit

@IBDesignable
class CircleBackgroundView: UIView {

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.size.width / 2
        layer.masksToBounds = true
    }

}
Maciej
quelle
1
Ausgezeichnet. Dies ist der richtige, adaptive Ansatz.
Womble
14

Swift 3 Klasse:

import UIKit

class CircleView: UIView {

    override func draw(_ rect: CGRect) {
        guard let context = UIGraphicsGetCurrentContext() else {return}

        context.addEllipse(in: rect)
        context.setFillColor(.blue.cgColor)
        context.fillPath()
    }           
}
Vyacheslav
quelle
6

Eine andere Möglichkeit, sich dem Zeichnen von Kreisen (und anderen Formen) zu nähern, ist die Verwendung von Masken. Sie zeichnen Kreise oder andere Formen, indem Sie erstens Masken mit den gewünschten Formen erstellen, zweitens Quadrate Ihrer Farbe bereitstellen und drittens Masken auf diese Farbquadrate anwenden. Sie können entweder Maske oder Farbe ändern, um einen neuen benutzerdefinierten Kreis oder eine andere Form zu erhalten.

#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *area1;
@property (weak, nonatomic) IBOutlet UIView *area2;
@property (weak, nonatomic) IBOutlet UIView *area3;
@property (weak, nonatomic) IBOutlet UIView *area4;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.area1.backgroundColor = [UIColor blueColor];
    [self useMaskFor: self.area1];

    self.area2.backgroundColor = [UIColor orangeColor];
    [self useMaskFor: self.area2];

    self.area3.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:1.0];
    [self useMaskFor: self.area3];

    self.area4.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:0.5];
    [self useMaskFor: self.area4];        
}

- (void)useMaskFor: (UIView *)colorArea {        
    CALayer *maskLayer = [CALayer layer];
    maskLayer.frame = colorArea.bounds;
    UIImage *maskImage = [UIImage imageNamed:@"cirMask.png"];
    maskLayer.contents = (__bridge id)maskImage.CGImage;
    colorArea.layer.mask = maskLayer;
}

@end

Hier ist die Ausgabe des obigen Codes:

vier Kreise

matrix3003
quelle
2

Es gibt eine andere Alternative für faule Leute. Sie können den layer.cornerRadius Schlüsselpfad für Ihre Ansicht im Interface Builder festlegen . Wenn Ihre Ansicht beispielsweise eine Breite = Höhe von 48 hat , legen Sie Folgendes fest layer.cornerRadius = 24:

Geben Sie hier die Bildbeschreibung ein

Dies funktioniert jedoch nur, wenn Sie eine statische Größe der Ansicht haben (width/height is fixed)und der Kreis im Interface Builder nicht angezeigt wird.

user8675
quelle
1

Swift 3 - Xcode 8.1

@IBOutlet weak var myView: UIView!

override func viewDidLoad() {
    super.viewDidLoad() 

    let size:CGFloat = 35.0
    myView.bounds = CGRect(x: 0, y: 0, width: size, height: size)
    myView.layer.cornerRadius = size / 2
    myView.layer.borderWidth = 1
    myView.layer.borderColor = UIColor.Gray.cgColor        
}
Mohammad Razipour
quelle