web-dev-qa-db-fra.com

Quelle est actuellement la "bonne" méthode pour définir le rayon de coin d'un UIView?

Définir un rayon de coin de UIView peut être effectué de la manière suivante:

  1. Définissez la propriété layer 's cornerRadius:

    view.layer.cornerRadius = 5;
    view.layer.masksToBounds = true;
    
  2. Appliquez un masque:

    func roundCorners(corners:UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
    
  3. Remplacer draw(_:):

    func draw(_ rect: CGRect) {
        // Size of rounded rectangle
        let rectWidth = rect.width
        let rectHeight = rect.height
    
        // Find center of actual frame to set rectangle in middle
        let xf: CGFloat = (self.frame.width  - rectWidth)  / 2
        let yf: CGFloat = (self.frame.height - rectHeight) / 2
    
        let ctx = UIGraphicsGetCurrentContext()!
        ctx.saveGState()
    
        let rect = CGRect(x: xf, y: yf, width: rectWidth, height: rectHeight)
        let clipPath = UIBezierPath(roundedRect: rect, cornerRadius: rectCornerRadius).cgPath
    
        ctx.addPath(clipPath)
        ctx.setFillColor(rectBgColor.cgColor)
    
        ctx.closePath()
        ctx.fillPath()
        ctx.restoreGState()
    }
    

Lequel de ceux-ci est généralement considéré comme le "bon" moyen d'implémenter des angles arrondis sur un UIView, en tenant compte des critères suivants:

  • configuration (certains coins peuvent être arrondis alors que d'autres ne le sont pas)
  • animation (pouvez-vous animer le changement de cornerRadius)
  • flexibilité (cela casse-t-il des bibliothèques tierces ou des masques que vous avez déjà appliqués)
  • lisibilité (la solution est-elle concise/réutilisable)
  • vitesse (cela a-t-il un impact négatif sur les performances)
7
GoldenJoe

Re vos trois options:

  1. Utilisation de CALayerpropriétés existantes: il s'agit d'une solution facile (et probablement la plus efficace) pour le masquage de coin simple. C'est animable aussi. Dans iOS 11, vous pouvez choisir les coins masqués.

  2. Concernant les masques CAShapeLayerpersonnalisés: c’est une bonne approche si le masquage des coins n’est pas un simple arrondi mais des chemins arbitraires. Vous devez faire attention à mettre à jour ce masque si le framechange (par exemple, dans layoutSubviewsNAME_ of view ou dans viewDidLayoutSubviewsNAME_ of controller). L'animation nécessite plus de travail.

  3. Re custom draw(_:) : Il s’agit de plus de travail que nécessaire et vous ne bénéficiez probablement pas des optimisations que l’équipe d’Apple a peut-être effectuées en arrière-plan (par exemple, si les appels drawsuivants ne dessinent qu’une partie du nom complet boundsle code redessine le tout malgré tout).

Je suggérerais l'option 1 pour les cas simples et l'option 2 si vous avez besoin de plus de contrôle que l'option 1 ne peut en offrir. Mais il n'y a pas de "meilleure" approche: cela dépend de ce dont vous avez besoin et de la quantité de travail que vous êtes prêt à accomplir.

7
Rob

J'ai fait quelques tests avec iOS 11 ou une version antérieure et la meilleure pratique que j'ai découverte pour contourner un coin ou tous les coins, vous pouvez le faire avec le code suivant.

// Full size
CGSize vSize = [UIScreen mainScreen].bounds.size;

// Object
UIView *viewTest = [[UIView alloc] initWithFrame: CGRectMake(0, 0, vSize.width, vSize.height)];
[viewTest setAutoresizingMask: UIViewAutoresizingFlexibleHeight];
[viewTest setBackgroundColor: [UIColor grayColor]];

// maskedCorners is only available in iOS 11
if (@available(iOS 11.0, *)) {
    [viewTest setClipsToBounds: YES];
    [viewTest.layer setCornerRadius: 10];

    // Only if you want to round the left and right top corners
    [viewTest.layer setMaskedCorners: kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner];
}
else {
    // The old way used in lower version
    CAShapeLayer *cartCornersRound = [CAShapeLayer layer];
    [cartCornersRound setPath: [UIBezierPath bezierPathWithRoundedRect: viewTest.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath];
    [viewTest.layer setMask: cartCornersRound];
}
  • Ce code corrige le problème avec autoResizingMask ne fonctionne pas lorsqu'il utilise l'ancienne méthode pour arrondir les angles.
  • Corrige un bug avec UIScrollView avec des coins arrondis et setContentSize major à la hauteur de l'objet.

La version Swift c'est quelque chose comme ça

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 8
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
6
Ladd.c

Je pense que ceci est le résumé le plus complet de tous: http://texturegroup.org/docs/corner-rounding.html

Mon heuristique est que si la vue n'a pas besoin de hautes performances (par exemple, ce n'est pas dans une cellule de vue de tableau), l'option la plus simple est d'utiliser la variable cornerRadius de CALayer. Si vous avez besoin d'un rayon de coin plus avancé ou de performances élevées, il est préférable d'explorer d'autres options.

5
gskbyte

Je vais avec le premier, c'est la façon la plus propre de le faire et vous pouvez le faire dans le IDE sans code. Ouvrez l'inspecteur d'attributs, puis cliquez sur l'inspecteur d'identité et ajoutez sous "Attributs d'exécution définis par l'utilisateur" ces 2 propriétés:

 enter image description here

1
Alexander Luna