ios - color - Agregue un borde fuera de una UIView(en lugar de adentro)
shadow view swift 4 (7)
Aumente el ancho y la altura 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;
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 como se muestra a continuación:
la vista derecha es la vista original, como puede ver, el área negra de la vista limitada es menor que la original. pero lo que quiero obtener es un borde fuera de la vista original, como este: . el área negra es igual a la original, ¿cómo puedo implementarla?
Bueno, no hay un método directo para hacerlo. Puedes considerar algunas soluciones.
- Cambie y aumente el marco y agregue bordercolor como lo hizo
- Agregue una vista detrás de la vista actual con el tamaño más grande para que aparezca como borde.Se puede trabajar como una clase de vista personalizada
Si no necesita un borde definido (borde borrado), entonces 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;
Con la mejor respuesta aceptada anteriormente, hice experiencias con resultados tan poco agradables y bordes desagradables:
Por lo tanto, 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()
Lamentablemente, no hay simplemente una pequeña propiedad que puede establecer para alinear el borde con el exterior. Dibuja alineado con el interior porque las operaciones de dibujo predeterminadas de UIViews se dibujan dentro de sus límites.
La solución más simple que se me ocurre es expandir la UIView por el tamaño del ancho del borde al aplicar el borde:
CGFloat borderWidth = 2.0f;
self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth);
self.layer.borderColor = [UIColor yellowColor].CGColor;
self.layer.borderWidth = borderWidth;
Me gustó la solución de @picciano. Si desea un círculo explosivo en lugar de 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
}
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 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 un CALayer
es más ligero que un UIView
y no tienes que modificar el marco de myView
, que es bueno, por ejemplo, si myView
es un UIImageView
NB: Para mí, el resultado no era 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 era exactamente lo que se solicita en el dispositivo real.
EDITAR
En realidad, el problema del que hablo en el NB fue simplemente porque reduje la pantalla del simulador, en tamaño normal no hay ningún problema
Espero eso ayude
Para una implementación Swift, puede agregar esto como una extensión 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()
}
}