ios - El color del borde de UIView en el constructor de interfaz no funciona?
objective-c swift (12)
Estoy intentando configurar las propiedades de capa de una vista a través de IB. Todo funciona, excepto el color del borde (propiedad layer.borderColor
):
Recuerdo haber tenido este problema hace un año y terminé haciéndolo programáticamente. Y aún así, puedo hacer esto programáticamente, pero tengo curiosidad por saber por qué la propiedad layer.borderColor
nunca funciona a través del constructor de interfaces. No quiero importar QuartzCore
, y luego escribir una línea adicional de código solo por esto, parece una exageración.
Aquí hay una manera rápida de superar esto. Categorías ...
@interface UIView (IBAppearance)
@property (nonatomic, strong) UIColor *borderColor;
@end
No tiene que almacenarlo, es simplemente agradable para que pueda consultar más tarde. Lo importante es tomar el valor y asignar el CGColor de UIColor a la capa.
#import <objc/runtime.h>
#define BORDER_COLOR_KEYPATH @"borderColor"
@implementation UIView (IBAppearance)
- (void)setBorderColor:(UIColor *)borderColor {
UIColor *bc = objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
if(bc == borderColor) return;
else {
objc_setAssociatedObject(self, BORDER_COLOR_KEYPATH, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.layer.borderColor = [borderColor CGColor];
}
}
- (UIColor *)borderColor {
return objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
}
@end
Por supuesto, en Interface Builder no está estableciendo el valor en layer.borderColor
, sino simplemente en borderColor
.
Copie y pegue esta clase:
import UIKit
@IBDesignable class BorderView : UIView {
@IBInspectable var borderColor: UIColor = .clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
@IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
Ahora en Interface Builder, vaya al inspector de identidad y configure su vista como una clase CustomView.
Después de eso, revisa tu Inspector de Atributos:
Ya no es necesario perder el tiempo con los atributos de tiempo de ejecución definidos por el usuario. ¡Y tus cambios también aparecerán en el lienzo!
Creo que puede ser porque tienes masksToBounds establecidos en SÍ. No creo que el borde esté dibujado dentro de los límites de la capa, por lo que no se dibujará ya que está ocultando todo fuera de sus límites.
Debes crear Categoría para CALayer:
CALayer + UIColor.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer(UIColor)
// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;
@end
CALayer + UIColor.m
#import "CALayer+UIColor.h"
@implementation CALayer(UIColor)
- (void)setBorderUIColor:(UIColor*)color {
self.borderColor = color.CGColor;
}
- (UIColor*)borderUIColor {
return [UIColor colorWithCGColor:self.borderColor];
}
@end
Y luego, en los atributos de Tiempo de ejecución definido por el usuario, puede usarlo tal como está en la imagen a continuación:
Para Swift es mucho más simple:
@IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
layer.borderWidth = 1
}
}
Entonces en Xcode puedes usarlo así:
Una vez que elige algo, se agrega automáticamente a sus atributos de tiempo de ejecución :
En Swift, puede extender la clase UIButton
y agregar una @IBInspectable
que le permitirá seleccionar un color del guión gráfico y establecer su color (con un ancho de 1 que se puede cambiar). Agregue esto al final de su controlador de vista:
extension UIButton{
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(CGColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.CGColor
layer.borderWidth = 1
}
}
}
Es posible hacer esto, pero no es una característica incorporada. Esto se debe a que el tipo de Color
en el panel Atributos de tiempo de ejecución definido por el usuario crea un UIColor
, pero layer.borderColor
contiene un tipo CGColorRef
. Desafortunadamente, no hay forma de asignar un tipo CGColorRef
en Interface Builder.
Sin embargo, esto es posible a través de una propiedad proxy. Vea la respuesta de Peter DeWeese a una pregunta diferente para una posible solución a este problema. Su respuesta define una categoría que permite establecer un color de proxy a través de Interface Builder.
Me encontré con el mismo problema, trabajé alrededor creando una clase de botón personalizada:
class UIButtonWithRoundBorder: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = 6
self.layer.borderWidth = 1
self.layer.borderColor = UIColor.whiteColor().CGColor
self.clipsToBounds = true
}
}
Luego, en IB, cambie el tipo de "UIButton" a "UIButtonWithRoundBorder".
Simple y práctico también. :)
Mis dos centavos por trasladar la respuesta de Bartłomiej Semańczyk a Swift:
Cree una extensión para CALayer en su controlador de vista:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
Para hacer que CALayer KVC cumpla con la propiedad borderColorFromUIColor, simplemente implemente
layer.borderColorFromUIColor=[UIColor red];
Puede establecer un valor para la clave "borderColor" en el XIB y usar:
extension UIView {
open override func setValue(_ value: Any?, forKey key: String) {
guard key == "borderColor", let color = value as? UIColor else {
super.setValue(value, forKey: key)
return
}
layer.borderColor = color.cgColor
}
}
Use IBDesignable en lugar de Atributos de tiempo de ejecución, es más claro.
Coloque este código en cualquier clase y edite las propiedades directamente en el guión gráfico.
import UIKit
@IBDesignable extension UIView {
@IBInspectable var borderColor:UIColor? {
set {
layer.borderColor = newValue!.CGColor
}
get {
if let color = layer.borderColor {
return UIColor(CGColor:color)
}
else {
return nil
}
}
}
@IBInspectable var borderWidth:CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
@IBInspectable var cornerRadius:CGFloat {
set {
layer.cornerRadius = newValue
clipsToBounds = newValue > 0
}
get {
return layer.cornerRadius
}
}
}
borderColor
no funcionará A MENOS borderWidth
propiedad borderWidth
de la capa esté configurada en un valor mayor que 0 .
Swift 3:
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1.0 // Default value is 0, that''s why omitting this line will not make the border color show.