[英]UIView's border color in Interface builder doesn't work?
I am trying to set up a view's layer properties via IB.我正在尝试通过 IB 设置视图的图层属性。 Everything works except for color of the border (property
layer.borderColor
):除了边框的颜色(属性
layer.borderColor
)之外,一切都有效:
I remember running into this problem a year ago and I ended up doing it programatically.我记得一年前遇到了这个问题,我最终以编程方式解决了这个问题。 And still, I can do this programmatically, but I am curious why the
layer.borderColor
property never works via interface builder.而且,我仍然可以通过编程方式执行此操作,但我很好奇为什么
layer.borderColor
属性从不通过界面生成器工作。 I don't want to import QuartzCore
, and then write extra line of code just because of this, seems like an overkill.我不想导入
QuartzCore
,然后仅仅因为这个而编写额外的代码行,这似乎是一种矫枉过正。
It's possible to do this, but it's not a built-in feature.可以这样做,但这不是内置功能。 This is because the
Color
type in the User Defined Runtime Attributes panel creates a UIColor
, but layer.borderColor
holds a CGColorRef
type.这是因为 User Defined Runtime Attributes 面板中的
Color
类型创建了一个UIColor
,但layer.borderColor
拥有一个CGColorRef
类型。 Unfortunately, there's no way to assign a CGColorRef
type in Interface Builder.不幸的是,没有办法在 Interface Builder 中分配
CGColorRef
类型。
However, this is possible through a proxy property.但是,这可以通过代理属性实现。 See Peter DeWeese's answer to a different question for a possible solution to this problem.
有关此问题的可能解决方案,请参阅Peter DeWeese 对不同问题的回答。 His answer defines a category that allows a proxy color to be set through Interface Builder.
他的回答定义了一个类别,允许通过 Interface Builder 设置代理颜色。
You have to create Category for CALayer:您必须为 CALayer 创建类别:
CALayer+UIColor.h 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 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
And then in User Defined Runtime attributes You can use it as it is on image below:然后在用户定义的运行时属性中,您可以使用它,如下图所示:
For Swift it is much more simple:对于Swift ,它要简单得多:
import QuartzCore
extension CALayer {
@IBInspectable var borderUIColor: UIColor? {
get {
guard let borderColor = borderColor else { return nil }
return UIColor(cgColor: borderColor)
}
set {
borderColor = newValue?.cgColor
}
}
}
Then in Xcode you can use it like this:然后在 Xcode 中你可以像这样使用它:
Once you choose sth it is automatically added to your runtime attributes :一旦你选择了某事,它就会自动添加到你的运行时属性中:
Copy and paste this class:复制并粘贴此类:
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
}
}
}
Now in Interface Builder, go to the Identity inspector and set your view as a CustomView class.现在在 Interface Builder 中,转到 Identity 检查器并将您的视图设置为 CustomView 类。
After that, check out your Attributes Inspector:之后,检查您的属性检查器:
No need to mess around with user defined runtime attributes anymore.不再需要弄乱用户定义的运行时属性。 And your changes will also show up on the canvas!
您的更改也将显示在画布上!
My two cents for porting Bartłomiej Semańczyk's answer to Swift:将 Bartłomiej Semańczyk 对 Swift 的回答移植到我的两分钱:
Create an extension for CALayer in your view controller:在视图控制器中为 CALayer 创建一个扩展:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
Use IBDesignable instead of Runtime Attributes it is more clear.使用 IBDesignable 而不是运行时属性更清楚。
Put this code in any class and edit the properties direct on the storyboard.将此代码放在任何类中并直接在情节提要上编辑属性。
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
}
}
}
Here's a quick way to overcome this.这是克服这个问题的快速方法。 Categories...
类别...
@interface UIView (IBAppearance)
@property (nonatomic, strong) UIColor *borderColor;
@end
You don't have to store it, it's just nice so you can query later.您不必存储它,它很好,因此您可以稍后查询。 The important thing is taking the value and assigning the UIColor's CGColor to the layer.
重要的是取值并将 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
Of course, in the Interface Builder you're not setting the value on layer.borderColor
, rather just on borderColor
.当然,在 Interface Builder 中,您不会在
layer.borderColor
上设置值,而只是在borderColor
上设置值。
In Swift, you can extend the UIButton
class and add an @IBInspectable
that will enable you to select a color from storyboard and set it's color (with width of 1 which can be changed).在 Swift 中,您可以扩展
UIButton
类并添加一个@IBInspectable
,使您能够从情节提要中选择一种颜色并设置它的颜色(宽度为 1,可以更改)。 Add this at the end of your view controller:在视图控制器的末尾添加:
extension UIButton{
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(CGColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.CGColor
layer.borderWidth = 1
}
}
}
In order to make CALayer KVC-compliant for the property borderColorFromUIColor, simply implement the为了使 CALayer KVC 兼容属性borderColorFromUIColor,只需实现
layer.borderColorFromUIColor=[UIColor red];
I met the same issue, I worked around it by creating a custom button class:我遇到了同样的问题,我通过创建一个自定义按钮类来解决它:
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
}
}
Then in IB, change the type from "UIButton" to "UIButtonWithRoundBorder".然后在 IB 中,将类型从“UIButton”更改为“UIButtonWithRoundBorder”。
Simple and handy too.简单又好用。 :)
:)
swift4斯威夫特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
will not work UNLESS the borderWidth
property of the layer is set to a value greater than 0 .除非图层的
borderWidth
属性设置为大于0的值,否则borderColor
将不起作用。
Swift 3:斯威夫特 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.
You can set a value for the "borderColor" key in the XIB and use:您可以在 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
}
}
I think it may be because you have masksToBounds set to YES.我认为这可能是因为您将 maskToBounds 设置为 YES。 I don't think the border is drawn within the bounds of the layer, so it won't be drawn since you're hiding everything outside of its bounds.
我不认为边界是在图层的边界内绘制的,所以它不会被绘制,因为你将所有东西都隐藏在它的边界之外。
You can customise border with 2 methods.您可以使用 2 种方法自定义边框。 First one is this.
第一个是这个。 Just click on the object go to the identity inspector and set the attributes.
只需单击对象转到身份检查器并设置属性。
Second one is this.第二个是这个。 make an IBOutlet of required object and put this code in view did load.
制作所需对象的 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 - Answer of Fede Henze's 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
}
}
}
try this in User Defined Runtime attribute :在用户定义的运行时属性中试试这个:
layer.borderUIColor
layer.borderUIColor
Color
Color
--you prefered color--
--you prefered color--
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.