web-dev-qa-db-ja.com

Interface BuilderでのUIViewの境界線の色が機能しませんか?

IBを使用してビューのレイヤープロパティを設定しようとしています。境界線の色(プロパティlayer.borderColor):

enter image description here

私は1年前にこの問題に遭遇したことを覚えており、プログラムでそれをやった。それでも、プログラムでこれを行うことはできますが、なぜlayer.borderColorpropertyは、インターフェイスビルダーでは機能しません。 QuartzCoreをインポートしたくないので、このためだけに余分なコード行を記述しますが、これはやり過ぎのようです。

64
0xSina

これを行うことは可能ですが、組み込みの機能ではありません。これは、[ユーザー定義のランタイム属性]パネルのColorタイプがUIColorを作成しますが、layer.borderColorCGColorRef型を保持します。残念ながら、Interface BuilderでCGColorRef型を割り当てる方法はありません。

ただし、これはプロキシプロパティを介して可能です。 Peter DeWeeseの答え を参照して、この問題の可能な解決策について別の質問に答えてください。彼の答えは、Interface Builderでプロキシカラーを設定できるカテゴリを定義しています。

76
mopsled

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で以下の画像のように使用できます:

enter image description here

Swiftの場合、はるかに簡単です。

@IBInspectable var borderColor: UIColor? {
    didSet {
        layer.borderColor = borderColor?.CGColor
        layer.borderWidth = 1
    }
}

次に、Xcodeで次のように使用できます。

enter image description here

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クラスとして設定します。

その後、属性インスペクターをチェックアウトします。

Attributes inspector with the new IBInspectable options

ユーザー定義のランタイム属性をいじる必要はもうありません。また、変更はキャンバスにも表示されます!

20
etayluz

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
    }
}
18
Eduardo

ランタイム属性の代わりに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
        }
    }
}
9
Fede Henze

これを克服する簡単な方法を次に示します。カテゴリー...

@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に値を設定するだけです。

5
bainfu

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
        }
    }
}
4
HusseinB

プロパティborderColorFromUIColorに対してCALayer KVCに準拠させるには、単に

layer.borderColorFromUIColor=[UIColor red];

このリンクにはオーナがあります

3
Mohit

私は同じ問題に出会い、カスタムボタンクラスを作成することで回避しました。

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」に変更します。

シンプルで便利。 :)

2
RainCast

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)
   }
}
1
zheng

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
    }
}
0

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.
0
Malloc

2つの方法で境界線をカスタマイズできます。最初はこれです。オブジェクトをクリックして、IDインスペクターに移動し、属性を設定するだけです。

enter image description here

二つ目はこれです。必要なオブジェクトの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)
    }
0
Akbar Khan

MasksToBoundsがYESに設定されているためだと思います。境界線はレイヤーの境界内に描画されるとは思わないので、境界の外側にあるすべてのものを非表示にしているため、境界線は描画されません。

0
Chris C