我试图通过IB设置视图的图层属性。一切正常,除了边框的颜色(属性layer.borderColor
):
我记得一年前遇到此问题,但最终还是以编程方式完成了此工作。而且,我可以通过编程方式执行此操作,但是我很好奇为什么该layer.borderColor
属性永远无法通过界面生成器工作。我不想import QuartzCore
,然后仅仅因为这个原因而编写额外的代码行,这似乎有点过头了。
我试图通过IB设置视图的图层属性。一切正常,除了边框的颜色(属性layer.borderColor
):
我记得一年前遇到此问题,但最终还是以编程方式完成了此工作。而且,我可以通过编程方式执行此操作,但是我很好奇为什么该layer.borderColor
属性永远无法通过界面生成器工作。我不想import QuartzCore
,然后仅仅因为这个原因而编写额外的代码行,这似乎有点过头了。
Answers:
可以这样做,但这不是内置功能。这是因为“Color
用户定义的运行时属性”面板中的类型会创建一个UIColor
,但会layer.borderColor
保留一个CGColorRef
类型。不幸的是,无法CGColorRef
在Interface Builder中分配类型。
但是,这可以通过代理属性来实现。有关此问题的可能解决方案,请参阅Peter DeWeese对另一个问题的回答。他的答案定义了一个类别,该类别允许通过Interface Builder设置代理颜色。
您必须为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
然后在“用户定义的运行时”属性中,可以按照下图所示使用它:
对于Swift,它要简单得多:
@IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
layer.borderWidth = 1
}
}
然后在Xcode中可以像这样使用它:
选择sth后,它将自动添加到您的运行时属性中:
assign
代替strong
?这是一个对象类型,这不会导致问题吗?
复制并粘贴此类:
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
}
}
}
现在,在Interface Builder中,转到身份检查器,然后将视图设置为CustomView类。
之后,请检查您的属性检查器:
不再需要弄乱用户定义的运行时属性。您所做的更改也将显示在画布上!
我为将BartłomiejSemańczyk的答案移植到Swift而付出的两分钱:
在视图控制器中为CALayer创建扩展:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
使用IBDesignable代替运行时属性会更清楚。
将此代码放在任何类中,然后直接在情节提要上编辑属性。
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
}
}
}
这是克服此问题的快速方法。分类...
@interface UIView (IBAppearance)
@property (nonatomic, strong) UIColor *borderColor;
@end
您不必存储它,这很好,因此您以后可以查询。重要的是获取值并将UIColor的CGColor分配给图层。
#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
当然,在Interface Builder中,您不是将值设置为layer.borderColor
,而是将值设置为borderColor
。
我遇到了同样的问题,我通过创建自定义按钮类来解决此问题:
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
}
}
然后在IB中,将类型从“ UIButton”更改为“ UIButtonWithRoundBorder”。
也简单方便。:)
迅捷4
extension CALayer {
open override func setValue(_ value: Any?, forKey key: String) {
/// If key is borderColor, and the value is the type of a UIColor.
if key == "borderColor" , let color = value as? UIColor {
/// After converting UIColor to CGColor, call the system method.
return super.setValue(color.cgColor, forKey: key)
}
super.setValue(value, forKey: key)
}
}
borderColor
除非borderWidth
图层的属性设置为大于0的值,否则它将不起作用。
斯威夫特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.
我认为可能是因为您将masksToBounds设置为YES。我不认为边界是在图层边界内绘制的,因此不会绘制边界,因为您将所有内容都隐藏在边界之外。
您可以在XIB中为“ borderColor”键设置一个值,并使用:
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
}
}
您可以使用2种方法自定义边框。第一个是这个。只需单击对象,转到身份检查器并设置属性。
第二个是这个。制作所需对象的IBOutlet并将此代码放入已加载的视图中。
@IBOutlet weak var uploadView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
uploadView.layer.cornerRadius = 10
uploadView.layer.borderWidth = 1.0
uploadView.layer.borderColor = #colorLiteral(red: 0.08235294118, green: 0.5058823529, blue: 0.9450980392, alpha: 1)
}
Swift 5.2-Fede Henze的答案
@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
}
}
}