Si agrega un borde de una vista usando código en una vista como
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = 2.0f;
el borde se agrega dentro de la vista de la siguiente manera:
la vista de la derecha es la vista original, como puede ver, el área negra de la vista bordeada es menor que la original. pero lo que quiero llegar es una frontera fuera de vista original, como esto: . el área negra es igual al original, ¿cómo puedo implementarlo?
Ok, ya hay una respuesta aceptada, pero creo que hay una mejor manera de hacerlo, solo tienes que tener una nueva capa un poco más grande que tu vista y no enmascararla a los límites de la capa de la vista (que en realidad es el comportamiento predeterminado). Aquí está el código de ejemplo :
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;
Por supuesto, esto es si desea que su borde sea 1 unidad más grande, si desea más, adapte el
borderWidth
y el marco de la capa en consecuencia. Esto es mejor que usar una segunda vista un poco más grande ya que aCALayer
es más ligero que aUIView
y no tienes que modificar el marco demyView
, lo cual es bueno, por ejemplo, simyView
es unUIImageView
NB: Para mí, el resultado no fue perfecto en el simulador (la capa no estaba exactamente en la posición correcta, por lo que la capa era más gruesa en un lado a veces) pero fue exactamente lo que se pidió en un dispositivo real.
EDITAR
En realidad el problema del que hablo en el NB fue solo porque había reducido la pantalla del simulador, en tamaño normal no hay absolutamente ningún problema
Espero eso ayude
fuente
Con la mejor respuesta aceptada anteriormente, hice experiencias con resultados no agradables y bordes antiestéticos:
Así que compartiré mi extensión UIView Swift con usted, que usa un UIBezierPath en su lugar como contorno de borde, sin bordes antiestéticos (inspirado en @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() } }
Ejemplo:
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()
fuente
Para una implementación de Swift, puede agregar esto como una extensión de 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() } }
fuente
Bueno, no hay un método directo para hacerlo. Puede considerar algunas soluciones.
Si no necesita un borde definido (borde claro), puede depender de la sombra para el propósito
[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;
fuente
Aumente el ancho y el alto del marco de la vista con el ancho del borde antes de agregar el borde:
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;
fuente
En realidad, existe una solución muy sencilla. Simplemente configúrelos de esta manera:
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
fuente
Me gustó la solución de @picciano Si desea un círculo explosivo en lugar de un cuadrado, reemplace la función addExternalBorder con:
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 }
fuente
Me gustó la solución de @picciano y @Maksim Kniazev. También podemos crear un borde anular con lo siguiente:
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 }
fuente
La forma en que coloqué un borde alrededor de mi vista de IU (principal - SubscriptionAd) en Storyboard es colocarlo dentro de otra vista de IU (background - BackgroundAd). La UIView de fondo tiene un color de fondo que coincide con el color del borde que quiero, y la UIView principal tiene un valor de restricciones 2 en cada lado.
Vincularé la vista de fondo a mi ViewController y luego encenderé y apagaré el borde cambiando el color de fondo.
fuente
Rápido 5
extension UIView { fileprivate struct Constants { static let externalBorderName = "externalBorder" } func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) -> CALayer { 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.name = Constants.ExternalBorderName layer.insertSublayer(externalBorder, at: 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() } }
fuente