IBを使用してビューのレイヤープロパティを設定しようとしています。境界線の色(プロパティlayer.borderColor
):
私は1年前にこの問題に遭遇したことを覚えており、プログラムでそれをやった。それでも、プログラムでこれを行うことはできますが、なぜlayer.borderColor
propertyは、インターフェイスビルダーでは機能しません。 QuartzCore
をインポートしたくないので、このためだけに余分なコード行を記述しますが、これはやり過ぎのようです。
これを行うことは可能ですが、組み込みの機能ではありません。これは、[ユーザー定義のランタイム属性]パネルのColor
タイプがUIColor
を作成しますが、layer.borderColor
はCGColorRef
型を保持します。残念ながら、Interface BuilderでCGColorRef
型を割り当てる方法はありません。
ただし、これはプロキシプロパティを介して可能です。 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
そして、ser Defined Runtime attributesで以下の画像のように使用できます:
Swiftの場合、はるかに簡単です。
@IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
layer.borderWidth = 1
}
}
次に、Xcodeで次のように使用できます。
Sthを選択すると、自動的にruntime attributesに追加されます:
このクラスをコピーして貼り付けます:
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で、Identityインスペクターに移動し、ビューをCustomViewクラスとして設定します。
その後、属性インスペクターをチェックアウトします。
ユーザー定義のランタイム属性をいじる必要はもうありません。また、変更はキャンバスにも表示されます!
SwiftへのBartłomiejSemańczykの答えを移植するための私の2セント:
View Controllerで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
に値を設定するだけです。
Swiftでは、UIButton
クラスを拡張し、@IBInspectable
これにより、ストーリーボードから色を選択し、その色を設定できます(幅を1に変更できます)。これをView Controllerの最後に追加します:
extension UIButton{
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(CGColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.CGColor
layer.borderWidth = 1
}
}
}
プロパティborderColorFromUIColorに対してCALayer KVCに準拠させるには、単に
layer.borderColorFromUIColor=[UIColor red];
私は同じ問題に出会い、カスタムボタンクラスを作成することで回避しました。
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」に変更します。
シンプルで便利。 :)
Swift4
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)
}
}
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
}
}
borderColor
は、レイヤーのborderWidth
プロパティが値より大きいに設定されていない限り機能しません。
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.
2つの方法で境界線をカスタマイズできます。最初はこれです。オブジェクトをクリックして、IDインスペクターに移動し、属性を設定するだけです。
二つ目はこれです。必要なオブジェクトの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)
}
MasksToBoundsがYESに設定されているためだと思います。境界線はレイヤーの境界内に描画されるとは思わないので、境界の外側にあるすべてのものを非表示にしているため、境界線は描画されません。