Comment créer un UILabel à coins arrondis sur l'iPhone?

150

Existe-t-il un moyen intégré de créer des étiquettes UIL à coins arrondis? Si la réponse est non, comment procéderait-on pour créer un tel objet?

newtonapple
la source

Réponses:

229

iOS 3.0 et versions ultérieures

iPhone OS 3.0 et versions ultérieures prend en charge la cornerRadiuspropriété sur la CALayerclasse. Chaque vue a une CALayerinstance que vous pouvez manipuler. Cela signifie que vous pouvez obtenir des coins arrondis en une seule ligne:

view.layer.cornerRadius = 8;

Tu devras #import <QuartzCore/QuartzCore.h> connecter au framework QuartzCore pour accéder aux en-têtes et propriétés de CALayer.

Avant iOS 3.0

Une façon de le faire, que j'ai utilisée récemment, est de créer une sous-classe UIView qui dessine simplement un rectangle arrondi, puis de créer l'UILabel ou, dans mon cas, UITextView, une sous-vue à l'intérieur. Plus précisément:

  1. Créez une UIViewsous-classe et nommez-la quelque chose comme RoundRectView.
  2. Dans RoundRectViewla drawRect:méthode de, tracez un chemin autour des limites de la vue en utilisant des appels Core Graphics comme CGContextAddLineToPoint () pour les arêtes et CGContextAddArcToPoint () pour les coins arrondis.
  3. Créez une UILabelinstance et faites-en une sous-vue de RoundRectView.
  4. Définissez le cadre de l'étiquette sur quelques pixels incrustés des limites du RoundRectView. (Par exemple, label.frame = CGRectInset(roundRectView.bounds, 8, 8);)

Vous pouvez placer le RoundRectView sur une vue à l'aide d'Interface Builder si vous créez un UIView générique, puis modifiez sa classe à l'aide de l'inspecteur. Vous ne verrez pas le rectangle tant que vous n'aurez pas compilé et exécuté votre application, mais au moins vous pourrez placer la sous-vue et la connecter à des prises ou à des actions si nécessaire.

benzado
la source
1
view.layer.cornerRadius dessine toujours la vue entière (hors écran à la place lorsqu'elle est activée) et ce n'est qu'au niveau du calque CoreAnimation qu'il découpera votre vue. Le coût est que cela rendra la mise de n'importe quelle vue activée dans un UIScrollView, tuant vos performances de défilement.
Zac Bowling
L'utilisation de cornerRadius dans un UIScrollView va tuer vos performances de défilement? Je pourrais vous croire si nous parlons d'un UITableView, mais une seule vue à angle arrondi ne va pas arrêter le système de dessin de vue.
benzado
20
Si vous souhaitez effectuer cette opération dans Interface Builder au lieu de code, vous pouvez définir un attribut d'exécution défini par l'utilisateur avec le chemin de clé "layer.cornerRadius" dans l'inspecteur d'identité.
Chris Vasselli
142

Pour les appareils équipés d'iOS 7.1 ou version ultérieure, vous devez ajouter:

yourUILabel.layer.masksToBounds = YES;
yourUILabel.layer.cornerRadius = 8.0;
OscarWyck
la source
3
Définissez le rayon du coin, mais masksToBounds est lent pour le défilement / l'animation. Si vous définissez la couleur d'arrière-plan du calque par rapport à la vue, cela suffit en conjonction avec cornerRadius du calque sur 7.1 (où il aurait cessé de fonctionner avec uniquement cornerRadius).
Aaron Zinman le
22

Pour Swift IOS8 à partir de la réponse OScarsWyck:

yourUILabel.layer.masksToBounds = true
yourUILabel.layer.cornerRadius = 8.0
VBaarathi
la source
15
S'il vous plaît ne pas encombrer le débordement de pile avec des traductions de réponses Objective-C dans Swift, en particulier lorsque le seul changement dans ce cas est en train de changer YESpour true.
mluisbrown
7
Le changement dans ce cas est minime, mais en général, les traductions d'Objective-C vers Swift sont souvent très utiles.
CKP78
1
Que diriez-vous de modifier la réponse originale et d'y ajouter une traduction Swift?
Marián Černý
11
  1. vous avez un UILabelappelé: myLabel.
  2. dans votre importation de fichier "m" ou "h": #import <QuartzCore/QuartzCore.h>
  3. dans votre viewDidLoadécrivez cette ligne:self.myLabel.layer.cornerRadius = 8;

    • dépend de la façon dont vous voulez, vous pouvez changer la valeur cornerRadius de 8 à un autre nombre :)

Bonne chance

Gabriel
la source
11

Vous pouvez créer une bordure arrondie avec la largeur de la bordure de n'importe quel contrôle de cette manière: -

CALayer * l1 = [lblName layer];
[l1 setMasksToBounds:YES];
[l1 setCornerRadius:5.0];

// You can even add a border
[l1 setBorderWidth:5.0];
[l1 setBorderColor:[[UIColor darkGrayColor] CGColor]];


Remplacez simplement lblNamepar votre UILabel.

Remarque: - N'oubliez pas d'importer<QuartzCore/QuartzCore.h>

Piyush Dubey
la source
7

J'ai créé une UILabelsous-classe rapide pour obtenir cet effet. De plus, je règle automatiquement la couleur du texte sur noir ou blanc pour un contraste maximal.

Résultat

couleurs-arrondies-bordures

Postes SO utilisés:

Terrain de jeux

Collez simplement ceci dans un Playground iOS:

//: Playground - noun: a place where people can play

import UIKit

class PillLabel : UILabel{

    @IBInspectable var color = UIColor.lightGrayColor()
    @IBInspectable var cornerRadius: CGFloat = 8
    @IBInspectable var labelText: String = "None"
    @IBInspectable var fontSize: CGFloat = 10.5

    // This has to be balanced with the number of spaces prefixed to the text
    let borderWidth: CGFloat = 3

    init(text: String, color: UIColor = UIColor.lightGrayColor()) {
        super.init(frame: CGRectMake(0, 0, 1, 1))
        labelText = text
        self.color = color
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    func setup(){
        // This has to be balanced with the borderWidth property
        text = "  \(labelText)".uppercaseString

        // Credits to https://stackoverflow.com/a/33015915/784318
        layer.borderWidth = borderWidth
        layer.cornerRadius = cornerRadius
        backgroundColor = color
        layer.borderColor = color.CGColor
        layer.masksToBounds = true
        font = UIFont.boldSystemFontOfSize(fontSize)
        textColor = color.contrastColor
        sizeToFit()

        // Credits to https://stackoverflow.com/a/15184257/784318
        frame = CGRectInset(self.frame, -borderWidth, -borderWidth)
    }
}


extension UIColor {
    // Credits to https://stackoverflow.com/a/29044899/784318
    func isLight() -> Bool{
        var green: CGFloat = 0.0, red: CGFloat = 0.0, blue: CGFloat = 0.0, alpha: CGFloat = 0.0
        self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        let brightness = ((red * 299) + (green * 587) + (blue * 114) ) / 1000

        return brightness < 0.5 ? false : true
    }

    var contrastColor: UIColor{
        return self.isLight() ? UIColor.blackColor() : UIColor.whiteColor()
    }
}

var label = PillLabel(text: "yellow", color: .yellowColor())

label = PillLabel(text: "green", color: .greenColor())

label = PillLabel(text: "white", color: .whiteColor())

label = PillLabel(text: "black", color: .blackColor())
Besi
la source
6

Une autre méthode consiste à placer un png derrière le UILabel. J'ai des vues avec plusieurs étiquettes qui superposent un seul png d'arrière-plan contenant toutes les illustrations pour les étiquettes individuelles.

Alpinista
la source
6

xCode 7.3.1 iOS 9.3.2

 _siteLabel.layer.masksToBounds = true;
  _siteLabel.layer.cornerRadius = 8;
Ahmed Abdallah
la source
6

Si vous voulez coin arrondi d'objets comme interface utilisateur ( UILabel, UIView, UIButton, UIImageView) par storyboard puis définissez clip to boundstrue et définissez User Defined Runtime Attributeschemin clé comme layer.cornerRadius, type = Nombre et valeur = 9 (comme votre exigence)

Définir le clip sur les limites comme Définissez les attributs d'exécution définis par l'utilisateur comme

Nikhlesh Bagdiya
la source
4
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
    label.text = @"Your String.";
    label.layer.cornerRadius = 8.0;
    [self.view addSubview:label];
Gaurav Gilani
la source
3

Swift 3

Si vous voulez une étiquette arrondie avec une couleur d'arrière-plan, en plus de la plupart des autres réponses, vous devez également définir layerla couleur d'arrière-plan de. Cela ne fonctionne pas lors de la définition de la viewcouleur d'arrière-plan.

label.layer.cornerRadius = 8
label.layer.masksToBounds = true
label.layer.backgroundColor = UIColor.lightGray.cgColor

Si vous utilisez la mise en page automatique, souhaitez un peu de remplissage autour de l'étiquette et ne souhaitez pas définir la taille de l'étiquette manuellement, vous pouvez créer une sous-classe UILabel et remplacer la intrinsincContentSizepropriété:

class LabelWithPadding: UILabel {
    override var intrinsicContentSize: CGSize {
        let defaultSize = super.intrinsicContentSize
        return CGSize(width: defaultSize.width + 12, height: defaultSize.height + 8)
    }
}

Pour combiner les deux, vous devrez également définir label.textAlignment = center, sinon le texte serait aligné à gauche.

Marián Černý
la source
2

Dans Monotouch / Xamarin.iOS, j'ai résolu le même problème comme ceci:

UILabel exampleLabel = new UILabel(new CGRect(0, 0, 100, 50))
        {
            Text = "Hello Monotouch red label"
        };
        exampleLabel.Layer.MasksToBounds = true;
        exampleLabel.Layer.CornerRadius = 8;
        exampleLabel.Layer.BorderColor = UIColor.Red.CGColor;
        exampleLabel.Layer.BorderWidth = 2;
Daniele D.
la source
2

Fonctionne parfaitement dans Swift 2.0

    @IBOutlet var theImage: UIImageView! //you can replace this with any UIObject eg: label etc


    override func viewDidLoad() {
        super.viewDidLoad()
//Make sure the width and height are same
        self.theImage.layer.cornerRadius = self.theImage.frame.size.width / 2
        self.theImage.layer.borderWidth = 2.0
        self.theImage.layer.borderColor = UIColor.whiteColor().CGColor
        self.theImage.clipsToBounds = true

    }
Naishta
la source
2

Avez-vous essayé d'utiliser le UIButtongénérateur d'interface (qui a des coins arrondis) et d'expérimenter les paramètres pour le faire ressembler à une étiquette. si tout ce que vous voulez est d'afficher du texte statique à l'intérieur.

Naren
la source
2

Fonctionne très bien dans Xcode 8.1.2 avec Swift 3, testé en août 2017

"cornerRadius" est la propriété clé pour définir les bords arrondis, où si vous utilisez le même style pour toutes les étiquettes de votre application, je recommanderais une méthode d'extension.

Code:

 // extension Class
extension UILabel {

    // extension user defined Method
    func setRoundEdge() {
        let myGreenColor = (UIColor(red: -0.108958, green: 0.714926, blue: 0.758113, alpha: 1.0))
        //Width of border
        self.layer.borderWidth = 1.0
        //How much the edge to be rounded
        self.layer.cornerRadius = 5.0

        // following properties are optional
        //color for border
        self.layer.borderColor = myGreenColor.cgColor
        //color for text
        self.textColor = UIColor.red
        // Mask the bound
        self.layer.masksToBounds = true
        //clip the pixel contents
        self.clipsToBounds = true
    }
}

Production:

entrez la description de l'image ici

Pourquoi la méthode d'extension?

Créez un fichier Swift et ajoutez le code suivant, qui a la méthode Extention à la classe "UILabel", où cette méthode est définie par l'utilisateur mais fonctionnera pour toutes les étiquettes de votre application et aidera à maintenir la cohérence et le code propre, si vous changer n'importe quel style à l'avenir ne nécessite que dans la méthode d'extension.

BHUVANESH MOHANKUMAR
la source
0

En fonction de ce que vous faites exactement, vous pouvez créer une image et la définir comme arrière-plan par programme.

Steven Mayer
la source