Si vous ajoutez une bordure d’une vue à l’aide de code dans une vue telle que
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
la bordure est ajoutée à l'intérieur de la vue comme suit:
la vue de droite est la vue d'origine, comme vous pouvez le constater, la zone noire de la vue avec bordure est inférieure à celle d'origine. mais ce que je veux obtenir, c’est une bordure en dehors de la vue originale, comme ceci:. la zone noire est égale à celle d'origine, comment puis-je l'implémenter?
Malheureusement, il n'y a pas simplement une petite propriété que vous pouvez définir pour aligner la bordure sur l'extérieur. Il dessine aligné à l'intérieur car les opérations de dessin par défaut d'UIViews sont dessinées dans ses limites.
La solution la plus simple qui me vienne à l’esprit serait d’agrandir UIView de la taille de la largeur de la bordure lors de l’application de la bordure:
CGFloat borderWidth = 2.0f;
self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth);
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = borderWidth;
Ok, il y a déjà une réponse acceptée mais je pense qu'il y a une meilleure façon de le faire, il vous suffit d'avoir un nouveau calque un peu plus grand que votre vue et de ne pas le masquer aux limites du calque de la vue (qui est en fait le comportement par défaut). Voici l exemple de code :
CALayer * externalBorder = [CALayer layer];
externalBorder.frame = CGRectMake(-1, -1, myView.frame.size.width+2, myView.frame.size.height+2);
externalBorder.borderColor = [UIColor blackColor].CGColor;
externalBorder.borderWidth = 1.0;
[myView.layer addSublayer:externalBorder];
myView.layer.masksToBounds = NO;
Bien sûr, si vous voulez que votre bordure ait 1 unité de large, si vous en voulez plus, vous adaptez la variable borderWidth
et le cadre du calque en conséquence ... C'est mieux que d'utiliser une seconde vue un peu plus grande, car une CALayer
est plus claire. que UIView
et que vous n’ayez pas à modifier le cadre de myView
, ce qui est bien, par exemple, si myView
est une UIImageView
N.B: Pour moi, le résultat n'était pas parfait sur simulateur (le calque n'était pas exactement à la bonne position, donc il était parfois plus épais sur un côté), mais correspondait exactement à ce qui était demandé sur un appareil réel.
MODIFIER
En fait, le problème dont je parle dans le N.B était simplement parce que j'avais réduit l'écran du simulateur. En taille normale, il n'y a absolument aucun problème.
J'espère que ça aide
Eh bien, il n’existe aucune méthode directe pour le faireVous pouvez envisager certaines solutions de contournement.
Si vous n’avez pas besoin d’une bordure définie (bordure dégagée), vous pouvez vous en remettre à l’ombre
[view1 setBackgroundColor:[UIColor blackColor]];
UIColor *color = [UIColor yellowColor];
view1.layer.shadowColor = [color CGColor];
view1.layer.shadowRadius = 10.0f;
view1.layer.shadowOpacity = 1;
view1.layer.shadowOffset = CGSizeZero;
view1.layer.masksToBounds = NO;
Avec la meilleure réponse acceptée ci-dessus, j’ai fait des expériences avec de tels résultats pas sympas et des avantages inesthétiques:
Je partagerai donc avec vous mon extension UIView Swift, qui utilise plutôt UIBezierPath comme contour de bordure - sans bords inesthétiques (inspiré par @Fattie ):
// UIView+BezierPathBorder.Swift
import UIKit
extension UIView {
fileprivate var bezierPathIdentifier:String { return "bezierPathBorderLayer" }
fileprivate var bezierPathBorder:CAShapeLayer? {
return (self.layer.sublayers?.filter({ (layer) -> Bool in
return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil
}) as? [CAShapeLayer])?.first
}
func bezierPathBorder(_ color:UIColor = .white, width:CGFloat = 1) {
var border = self.bezierPathBorder
let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius)
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
if (border == nil) {
border = CAShapeLayer()
border!.name = self.bezierPathIdentifier
self.layer.addSublayer(border!)
}
border!.frame = self.bounds
let pathUsingCorrectInsetIfAny =
UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius)
border!.path = pathUsingCorrectInsetIfAny.cgPath
border!.fillColor = UIColor.clear.cgColor
border!.strokeColor = color.cgColor
border!.lineWidth = width * 2
}
func removeBezierPathBorder() {
self.layer.mask = nil
self.bezierPathBorder?.removeFromSuperlayer()
}
}
Exemple:
let view = UIView(frame: CGRect(x: 20, y: 20, width: 100, height: 100))
view.layer.cornerRadius = view.frame.width / 2
view.backgroundColor = .red
//add white 2 pixel border outline
view.bezierPathBorder(.white, width: 2)
//remove border outline (optional)
view.removeBezierPathBorder()
Pour une implémentation Swift, vous pouvez l'ajouter en tant qu'extension UIView.
extension UIView {
struct Constants {
static let ExternalBorderName = "externalBorder"
}
func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.whiteColor()) -> CALayer {
let externalBorder = CALayer()
externalBorder.frame = CGRectMake(-borderWidth, -borderWidth, frame.size.width + 2 * borderWidth, frame.size.height + 2 * borderWidth)
externalBorder.borderColor = borderColor.CGColor
externalBorder.borderWidth = borderWidth
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, atIndex: 0)
layer.masksToBounds = false
return externalBorder
}
func removeExternalBorders() {
layer.sublayers?.filter() { $0.name == Constants.ExternalBorderName }.forEach() {
$0.removeFromSuperlayer()
}
}
func removeExternalBorder(externalBorder: CALayer) {
guard externalBorder.name == Constants.ExternalBorderName else { return }
externalBorder.removeFromSuperlayer()
}
}
Augmentez la largeur et la hauteur du cadre de la vue avec la largeur de la bordure avant d'ajouter la bordure:
float borderWidth = 2.0f
CGRect frame = self.frame;
frame.width += borderWidth;
frame.height += borderWidth;
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
Il y a en fait une solution très simple. Il suffit de les définir comme ceci:
view.layer.borderWidth = 5
view.layer.borderColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5).cgColor
view.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.25).cgColor
J'ai aimé la solution de @picciano & @Maksim Kniazev. Nous pouvons également créer une bordure annulaire avec les éléments suivants:
func addExternalAnnularBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) {
let externalBorder = CALayer()
externalBorder.frame = CGRect(x: -borderWidth*2, y: -borderWidth*2, width: frame.size.width + 4 * borderWidth, height: frame.size.height + 4 * borderWidth)
externalBorder.borderColor = borderColor.cgColor
externalBorder.borderWidth = borderWidth
externalBorder.cornerRadius = (frame.size.width + 4 * borderWidth) / 2
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, at: 0)
layer.masksToBounds = false
}
J'ai aimé la solution de @picciano Si vous voulez un cercle explosif au lieu d'un carré, remplacez addExternalBorder function par:
func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) {
let externalBorder = CALayer()
externalBorder.frame = CGRect(x: -borderWidth, y: -borderWidth, width: frame.size.width + 2 * borderWidth, height: frame.size.height + 2 * borderWidth)
externalBorder.borderColor = borderColor.cgColor
externalBorder.borderWidth = borderWidth
externalBorder.cornerRadius = (frame.size.width + 2 * borderWidth) / 2
externalBorder.name = Constants.ExternalBorderName
layer.insertSublayer(externalBorder, at: 0)
layer.masksToBounds = false
}