Dare UIView angoli arrotondati


577

La mia vista di accesso ha una sottoview che ha un UIActivityViewe un UILabeldetto "Accesso ...". Questa sottoview ha angoli che non sono arrotondati. Come posso farli girare?

C'è un modo per farlo all'interno del mio xib?


6
Fare qualcosa del genere in IB richiederebbe un'immagine pre-renderizzata con angoli arrotondati
Ed Marty,

9
Non necessariamente @ ed-marty, questa risposta di @Gujamin merita un po 'più di credito in quanto mostra come applicare la cornerRadiusproprietà alla tabella utilizzando solo Interface Builder, senza dover utilizzare immagini pre-renderizzate o impostarle nel codice.
djskinner,

Risposte:


1219

Prova questo

#import <QuartzCore/QuartzCore.h> // not necessary for 10 years now  :)

...

view.layer.cornerRadius = 5;
view.layer.masksToBounds = true;

Nota: se si sta tentando di applicare gli angoli arrotondati alla UIViewControllervista di una, questa non dovrebbe essere applicata nel costruttore del controller della vista, ma piuttosto in -viewDidLoad, dopo che viewè effettivamente istanziata.


6
Nota che la proprietà esiste solo in iPhone 3.0, non nelle versioni precedenti.
Kendall Helmstetter Gelner,

5
Devo solo dire che questa è stata una delle risposte più immediatamente soddisfacenti che abbia mai visto su SO. Il controllo qui prima mi ha fatto risparmiare un'ora di combattimenti con un editor di immagini e avrebbe reso la mia vista più fragile alle modifiche di colore / dimensionamento. Grazie!
Justin Searls,

20
Nota correlata: chiunque sia interessato a più oggetti visivi (ad esempio ombra) da applicare facilmente a un UIView dovrebbe consultare il riferimento alla classe CALayer. La maggior parte è facile come impostare uno o due valori di proprietà, come la risposta sopra: developer.apple.com/mac/library/documentation/GraphicsImaging/…
Justin Searls

6
@Ben Collins (o chiunque altro abbia questo problema), assicurati che la tua vista abbia impostato "sottovoci clip". Puoi verificarlo nel generatore di interfaccia.
zem,

2
funziona benissimo MA se hai molti di questi angoli arrotondati in qualsiasi tipo di vista di scorrimento o animazione (ho provato a usarli in un UITableView) la tua performance ne risentirà notevolmente. La bella vista scorrevole della tabella diventa rapidamente instabile :(
Slee

261

È inoltre possibile utilizzare la funzione Attributi di runtime definiti dall'utente del builder di interfacce per impostare il percorso chiave layer.cornerRadiussu un valore. Assicurati di includere la QuartzCorelibreria però.

Questo trucco funziona anche per l'impostazione layer.borderWidth, tuttavia non funzionerà layer.borderColorperché si prevede un CGColornon a UIColor.

Non sarai in grado di vedere gli effetti nello storyboard perché questi parametri vengono valutati in fase di esecuzione.

Usando Interface builder per impostare il raggio dell'angolo


10
ricordati di selezionare anche l' Clip Subviewsopzione IB per la vista
Peter,

2
(o) aggiungi un percorso chiave: layer.masksToBounds, tipo: booleano: controllato
Amitabh

64

Ora puoi usare una categoria rapida in UIView (codice sotto l'immagine) con @IBInspectable per mostrare il risultato nello storyboard (se stai usando la categoria, usa solo cornerRadius e non layer.cornerRadius come percorso chiave.

extension UIView {
    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }
}

inserisci qui la descrizione dell'immagine


E se stai usando una sottoclasse personalizzata, assicurati di taggarla @IBDesignableper ottenere un'anteprima dal vivo in IB! (Altro su nshipster.com/ibinspectable-ibdesignable )
clozach

56

veloce

Risposta breve:

myView.layer.cornerRadius = 8
myView.layer.masksToBounds = true  // optional

Risposta supplementare

Se sei arrivato a questa risposta, probabilmente hai già visto abbastanza per risolvere il tuo problema. Sto aggiungendo questa risposta per dare un po 'più di spiegazione visiva al perché le cose fanno quello che fanno.

Se inizi con un normale UIView, ha degli angoli quadrati.

let blueView = UIView()
blueView.frame = CGRect(x: 100, y: 100, width: 100, height: 50)
blueView.backgroundColor = UIColor.blueColor()
view.addSubview(blueView)

inserisci qui la descrizione dell'immagine

Puoi dargli angoli arrotondati modificando la cornerRadiusproprietà della vista layer.

blueView.layer.cornerRadius = 8

inserisci qui la descrizione dell'immagine

Valori di raggio maggiori forniscono angoli più arrotondati

blueView.layer.cornerRadius = 25

inserisci qui la descrizione dell'immagine

e valori più piccoli danno angoli meno arrotondati.

blueView.layer.cornerRadius = 3

inserisci qui la descrizione dell'immagine

Questo potrebbe essere sufficiente per risolvere il tuo problema proprio lì. Tuttavia, a volte una vista può avere una vista secondaria o un gioco secondario che va oltre i limiti della vista. Ad esempio, se dovessi aggiungere una vista secondaria come questa

let mySubView = UIView()
mySubView.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubView.backgroundColor = UIColor.redColor()
blueView.addSubview(mySubView)

oppure se dovessi aggiungere un sub strato come questo

let mySubLayer = CALayer()
mySubLayer.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubLayer.backgroundColor = UIColor.redColor().CGColor
blueView.layer.addSublayer(mySubLayer)

Quindi finirei con

inserisci qui la descrizione dell'immagine

Ora, se non voglio che le cose siano sospese oltre i limiti, posso farlo

blueView.clipsToBounds = true

o questo

blueView.layer.masksToBounds = true

che dà questo risultato:

inserisci qui la descrizione dell'immagine

Entrambi clipsToBoundse masksToBoundssono equivalenti . È solo che il primo viene utilizzato con UIViewe il secondo viene utilizzato con CALayer.

Guarda anche


4
Vorrei anche aggiungere che impostando il raggio dell'angolo a metà del lato più corto (in questo caso blueView.frame.size.height/2) si ottiene un angolo perfettamente arrotondato.
Johann Burgess,

44

Un approccio diverso rispetto a quello di Ed Marty:

#import <QuartzCore/QuartzCore.h>

[v.layer setCornerRadius:25.0f];
[v.layer setMasksToBounds:YES];

Hai bisogno di setMasksToBounds per caricare tutti gli oggetti da IB ... ho avuto un problema in cui la mia vista era arrotondata, ma non avevo gli oggetti da IB: /

questo risolto = D spero che sia d'aiuto!


48
come è diverso? altro che non usare la sintassi del punto?
user102008

3
[v.layer setMasksToBounds: YES]; Questa linea è magica, risolve il mio grosso problema
Cullen SUN,

3
Ho scritto questo quando ho iniziato lo sviluppo di iOS e non sapevo che non ci fosse differenza tra la sintassi dei punti e la sintassi delle parentesi. Pertanto l'ho scritto come "diverso". Il mio codice includeva anche l'importazione <> che Ed Marty non aveva nella sua risposta originale (successivamente modificata in) e quindi la mia risposta aiuta le persone a risolvere il loro problema (ovvero non averlo importato).
Kristian Flatheim Jensen,

28

Come descritto in questo post del blog , ecco un metodo per arrotondare gli angoli di una UIView:

+(void)roundView:(UIView *)view onCorner:(UIRectCorner)rectCorner radius:(float)radius
{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                   byRoundingCorners:rectCorner
                                                         cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = view.bounds;
    maskLayer.path = maskPath.CGPath;
    [view.layer setMask:maskLayer];
    [maskLayer release];
}

La parte interessante è che puoi selezionare quali angoli vuoi arrotondare per eccesso.


6
Piuttosto che fornire semplicemente un collegamento a un sito esterno, preferiamo che le risposte siano autonome qui, quindi ho inserito il codice pertinente dal post di blog collegato nella tua risposta. Le persone possono visitare il post sul blog per maggiori dettagli, ma questo assicura che il contenuto sopravviverà se il post in questione scompare. Inoltre, hai inviato questa risposta a diverse domande che non hanno posto la stessa cosa. Furono rimossi e una domanda fu chiusa come duplicata di questa. Ci piace avere risposte elaborate per soddisfare ogni domanda.
Brad Larson

5
Preveggente. Il post sul blog è ora 404.
Anthony C,

Questo approccio è pulito ma nasconderà qualsiasi effetto ombra sulla vista.
martedì

19

Devi prima importare il file di intestazione <QuartzCore/QuartzCore.h>

 #import QuartzCore/QuartzCore.h>

[yourView.layer setCornerRadius:8.0f];
yourView.layer.borderColor = [UIColor redColor].CGColor;
yourView.layer.borderWidth = 2.0f;
[yourView.layer setMasksToBounds:YES];

Da non perdere setMasksToBounds, altrimenti l'effetto potrebbe non essere visualizzato.


2
Non è necessario importare "QuartzCore / QuartzCore.h"
Sudhir Kumar

Sì, devi importare.
Lord Zsolt,

3
@LordZsolt Forse l'hanno cambiato con iOS7, ma non è più necessario importare QuartzCore.
Marc,

15

È possibile utilizzare la seguente UIViewclasse personalizzata che può anche cambiare il colore e la larghezza del bordo. Poiché è IBDesignalbepossibile, è possibile modificare anche gli attributi nel generatore di interfaccia.

inserisci qui la descrizione dell'immagine

import UIKit

@IBDesignable public class RoundedView: UIView {

    @IBInspectable var borderColor: UIColor = UIColor.white {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }

    @IBInspectable var borderWidth: CGFloat = 2.0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }

}

6
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 200, 200)];

view.layer.backgroundColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 20.0;
view.layer.frame = CGRectInset(v.layer.frame, 20, 20);

view.layer.shadowOffset = CGSizeMake(1, 0);
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .25;

[self.view addSubview:view];
[view release];

L'applicazione di setMasksToBounds è importante. L'impostazione di un colore di sfondo e dell'ombra esterna non lo è.
djskinner,

3

Swift 4 - Utilizzo di IBDesignable

   @IBDesignable
    class DesignableView: UIView {
    }

    extension UIView
    {

        @IBInspectable
        var cornerRadius: CGFloat {
            get {
                return layer.cornerRadius
            }
            set {
            layer.cornerRadius = newValue
        }
    }
}

Mi dispiace, ma come nuovo arrivato allo sviluppo di IOS. In che modo la soluzione impedisce layer.cornerRadiusdi tornare allo stato originale? (ei come fa lo storyboard di xcode a sapere come impostare cornerRadiussolo dopo l' UIViewinizializzazione dell'originale )?
AlanSTACK


3

- SwiftUI

In SwiftUI, puoi utilizzare il cornerRadiusmodificatore direttamente su quello Viewche desideri. Ad esempio di questa domanda:

Text("Signing In…")
    .padding(16)
    .background(Color.red)
    .cornerRadius(50)

Anteprima

Nota che non c'è più un raggio simile al diamante, quindi anche se imposti l'angolo Radius a più della metà dell'altezza , si arrotonderà senza problemi.

Checkout questa risposta a sé come Angoli arrotondati specifici in SwiftUI


2

Si prega di importare Quartzcore frameworkquindi è necessario impostare setMaskToBoundssu TRUEquesto la linea molto importante.

Poi: [[yourView layer] setCornerRadius:5.0f];


2
UIView* viewWithRoundedCornersSize(float cornerRadius,UIView * original)
{
    // Create a white border with defined width
    original.layer.borderColor = [UIColor yellowColor].CGColor;
    original.layer.borderWidth = 1.5;

    // Set image corner radius
    original.layer.cornerRadius =cornerRadius;

    // To enable corners to be "clipped"
    [original setClipsToBounds:YES];
    return original;
}

2

Fallo programmaticamente in obj c

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 50,    200, 200)];

view.layer.backgroundColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 20.0;
view.layer.frame = CGRectInset(v.layer.frame, 20, 20);

[view.layer.shadowOffset = CGSizeMake(1, 0);
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .25;][1]

[self.view addSubview:view];

Possiamo farlo anche da stoaryboard.

 layer.cornerRadius  Number  5

inserisci qui la descrizione dell'immagine


2

se l'angolo arrotondato non funziona in viewDidload () è meglio scrivere codice in viewDidLayoutSubview ()

-(void)viewDidLayoutSubviews
{
    viewTextfield.layer.cornerRadius = 10.0 ;                                               
    viewTextfield.layer.borderWidth = 1.0f;
    viewTextfield.layer.masksToBounds =  YES;
    viewTextfield.layer.shadowRadius = 5;
    viewTextfield.layer.shadowOpacity = 0.3;
    viewTextfield.clipsToBounds = NO;
    viewTextfield.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
}

Spero che sia di aiuto!


0

Puoi anche usare un'immagine:

UIImage *maskingImage = [UIImage imageNamed:@"bannerBarBottomMask.png"];
CALayer *maskingLayer = [CALayer layer];
maskingLayer.frame = CGRectMake(-(self.yourView.frame.size.width - self.yourView.frame.size.width) / 2
                                , 0
                                , maskingImage.size.width
                                , maskingImage.size.height);
[maskingLayer setContents:(id)[maskingImage CGImage]];
[self.yourView.layer setMask:maskingLayer];

0

set cornerRadious Property per Round View

set masksToBounds Il valore booleano per l'immagine non verrà ancora disegnato al di fuori del limite del raggio dell'angolo

view.layer.cornerRadius = 5;

view.layer.masksToBounds = YES;

0

Utilizzando l'estensione UIView:

extension UIView {    

func addRoundedCornerToView(targetView : UIView?)
{
    //UIView Corner Radius
    targetView!.layer.cornerRadius = 5.0;
    targetView!.layer.masksToBounds = true

    //UIView Set up boarder
    targetView!.layer.borderColor = UIColor.yellowColor().CGColor;
    targetView!.layer.borderWidth = 3.0;

    //UIView Drop shadow
    targetView!.layer.shadowColor = UIColor.darkGrayColor().CGColor;
    targetView!.layer.shadowOffset = CGSizeMake(2.0, 2.0)
    targetView!.layer.shadowOpacity = 1.0
}
}

Uso:

override func viewWillAppear(animated: Bool) {

sampleView.addRoundedCornerToView(statusBarView)

}

0

In Swift 4.2 e Xcode 10.1

let myView = UIView()
myView.frame = CGRect(x: 200, y: 200, width: 200, height: 200)
myView.myViewCorners()
//myView.myViewCorners(width: myView.frame.width)//Pass View width
view.addSubview(myView)

extension UIView {
    //If you want only round corners
    func myViewCorners() {
        layer.cornerRadius = 10
        layer.borderWidth = 1.0
        layer.borderColor = UIColor.red.cgColor
        layer.masksToBounds = true
    }
    //If you want complete round shape, enable above comment line
    func myViewCorners(width:CGFloat) {
        layer.cornerRadius = width/2
        layer.borderWidth = 1.0
        layer.borderColor = UIColor.red.cgColor
        layer.masksToBounds = true
    }
}

-4

ON Xcode 6 La tua prova

     self.layer.layer.cornerRadius = 5.0f;

o

    self.layer.layer.cornerRadius = 5.0f;
    self.layer.clipsToBounds = YES;
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.