Come disegnare un UIView personalizzato che è solo un cerchio - app per iPhone


129

Come farei per disegnare un UIView personalizzato che è letteralmente solo una palla (un cerchio 2D)? Vorrei solo ignorare il metodo drawRect? E qualcuno può mostrarmi il codice per disegnare un cerchio blu?

Inoltre, sarebbe bene cambiare il frame di quella vista all'interno della classe stessa? O devo cambiare il frame da una classe diversa?

(sto solo cercando di piazzare una palla che rimbalza)

Risposte:


209

Puoi usare QuartzCore e fare qualcosa di simile -

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];

104
Cordiali saluti, affinché la vista sia un cerchio usando QuartCore, il raggio dell'angolo deve essere metà dell'altezza / larghezza della cornice. Questo è il modo più semplice per creare un cerchio, ma non è necessariamente il più efficiente. Se le prestazioni sono fondamentali, probabilmente DrawRect produrrà risultati migliori.
Benjamin Mayo,

4
E questo è. 100 è l'altezza / larghezza.
Kal

3
Sì, mi dispiace non averti diretto questo, Kal. Lo stavo menzionando a StanLe nel caso volesse usare viste di dimensioni diverse.
Benjamin Mayo,

Se la dimensione del tuo cerchio non è 100X100, l'angolo Radius dovrebbe essere il (nuovo formato) / 2
gran33

Ma ho notato che il cerchio con cornerradius ha talvolta bordi leggermente "piatti" / ritagliati. Almeno se usato con un bordo. Qualche idea sul perché? Il raggio è esattamente la metà della dimensione della vista. Ho pensato che potrebbe essere un problema di ritaglio, ma non sembra così, provato anche con un sublayer più piccolo - ha ancora lo stesso effetto.
Ixx,

135

Vorrei solo ignorare il metodo drawRect?

Sì:

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

Inoltre, sarebbe bene cambiare il frame di quella vista all'interno della classe stessa?

Idealmente no, ma potresti.

O devo cambiare il frame da una classe diversa?

Lascio che il genitore lo controlli.


1
Come posso impostare colori personalizzati, non solo blu? Cerco di usare il bianco e il blu in questo modo: ([self.colorOfCircle CGColor]) ma non succede nulla: \
gaussblurinc

@loldop è self.colorOfCircle un UIColor? È impostato? Se metti un breakpoint su quella linea e guardi il valore, è quello che ti aspetti? Se lo imposti dopo il fatto, dovrai invalidare la parte della vista che contiene il cerchio.
Steve,

9
uso @gaussblurinc CGContextSetFillColorWithColor(ctx, self.colorOfCircle.CGColor);, il metodo proposto nella soluzione CGColorGetComponentsfunziona solo con alcuni colori, vedere stackoverflow.com/questions/9238743/...
yonilevy

Nota a chiunque si blocchi su questo. Piuttosto che rect, ho usato accidentalmente self.frameper l'ellisse. Il valore corretto è self.bounds. D'oh! :)
Olie il

31

Ecco un altro modo usando UIBezierPath (forse è troppo tardi ^^) Crea un cerchio e maschera UIView con esso, come segue:

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;

1
Non c'è davvero bisogno di trasformare quella maschera di forma in una maschera; potresti semplicemente usare il livello forma direttamente come livello della vista e dargli un colore di riempimento. La maschera è probabilmente significativamente più costosa.
Jesse Rusak,

Il livello di UIView è CALayer, quindi come possiamo disegnare una forma su questo livello. Suppongo che aggiungiamo il livello forma al livello vista senza mascherarlo ??
Gintama,

1
Puoi sottoclassare UIView e sovrascrivere il layerClassmetodo class per renderlo un livello forma.
Jesse Rusak,

@JesseRusak, il problema che sto riscontrando con il tuo suggerimento (per impostare la forma sul livello di UIView stesso) è che non devi usare correttamente backgroundColor. Dovresti applicare fillColor e impostare backgroundColor su clearColor, il che significa che un utente di UIView non sarebbe in grado di impostare naturalmente backgroundColor.
Richard Venable,

25

Il mio contributo con un'estensione Swift:

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

Chiama soltanto myView.asCircle()


l'impostazione masksToBoundssu true e l'utilizzo selfsono tutti opzionali in questa risposta, ma è ancora la soluzione più breve e migliore
Max Desiatov

17

Swift 3 : classe personalizzata, facile da riutilizzare. Utilizza backgroundColorset nel builder UI

import UIKit

@IBDesignable
class CircleBackgroundView: UIView {

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

}

1
Eccellente. Questo è l'approccio corretto e adattivo.
Womble,

14

Swift 3 class:

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

6

Un altro modo per avvicinarsi al disegno del cerchio (e di altre forme) è usare le maschere. Disegni cerchi o altre forme, in primo luogo, creando maschere delle forme che ti servono, in secondo luogo, fornisci quadrati del tuo colore e, in terzo luogo, applichi maschere a quei quadrati di colore. Puoi cambiare maschera o colore per ottenere un nuovo cerchio personalizzato o un'altra forma.

#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

Ecco l'output del codice sopra:

quattro cerchi


2

C'è un'altra alternativa per i pigri. È possibile impostare il layer.cornerRadius percorso chiave per la vista in Interface Builder . Ad esempio, se la vista ha una larghezza = altezza di 48 , impostare layer.cornerRadius = 24:

inserisci qui la descrizione dell'immagine

Tuttavia, questo funziona solo se hai una dimensione statica della vista (width/height is fixed)e non mostra il cerchio nel builder dell'interfaccia.


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        
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.