Изменить цвет границы UIButton в раскадровке

80

Я устанавливаю CornerRadius и BorderWidth для UIbutton в определяемых пользователем атрибутах времени выполнения. Без добавления layer.borderColor он работает хорошо и отображает границу черным цветом. Но при добавлении layer.borderColor не работает (не показывает границу).

введите описание изображения здесь

Мохамед Джалил Назир
источник

Ответы:

159

Для Swift:

введите описание изображения здесь

Swift 3:

extension UIView {

    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(cgColor: layer.borderColor!)
        }
        set {
            layer.borderColor = newValue?.cgColor
        }
    }
}

Swift 2.2:

extension UIView {

    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(CGColor: layer.borderColor!)
        }
        set {
            layer.borderColor = newValue?.CGColor
        }
    }
}
Мохамед Джалил Назир
источник
привет, я создаю класс CustomeView в объекте c, но он не отображается в моей раскадровке. Пожалуйста, помогите мне.
Пуджа Шривастава
Большое спасибо за это! :)
Vijay VS
Спасибо, потрясающе, идеально
Abo3atef
1
Приятно, но XCode (версия 8.3.3 (8E3004b)) не показывает результат в предварительном просмотре, это правильно и нет возможности изменить (кроме создания пользовательского представления)?
Константин Берков
Это самое элегантное решение! Хорошая работа!
Золтан Винклер
88

Получил ответ. Измените borderColor вместо layer.borderColor :

Фрагмент Xcode

и добавьте этот код в файл .m:

#import <QuartzCore/QuartzCore.h>
@implementation CALayer (Additions)

- (void)setBorderColorFromUIColor:(UIColor *)color
{
    self.borderColor = color.CGColor;
}

@end

Свойства галочки в Attribute Inspector

Инспектор атрибутов

Мохамед Джалил Назир
источник
5
@jithin Я написал это как расширение Swift, вот код: extension CALayer {func setBorderColorFromUIColor (color: UIColor) {self.borderColor = color.CGColor}}
Guy
1
уловка сработала. частично. как, черт возьми, я получаю черный цвет границы, хотя я указал красный цвет? !!!!!! есть идеи? кто угодно?
static0886
@ static0886: Это было из-за того, что цвет, который вы применяете, не установлен для границы. Насколько я понимаю, мы не можем установить цвет границы из раскадровки, так как это свойство не будет отражено в UIComponent во время выполнения. По умолчанию это черный цвет. Если вы хотите попробовать, удалите свойство цвета из атрибутов.
Javeed
Для быстрого вы можете установить его как: self.button.layer.borderColor = <UIColor.CGColor>
Sam
Этот layer.borderColorFromUIColor работал у меня в раскадровке. Спасибо.
Рамакришна
50

Swift 4, Xcode 9.2 - Используйте IBDesignableи IBInspectableдля создания настраиваемых элементов управления и предварительного просмотра дизайна в Интерфейсном Разработчике.

Вот пример кода в Swift, поместите чуть ниже UIKitViewController.swift:

@IBDesignable extension UIButton {

    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }
}

Если вы перейдете к проверяемым атрибутам представления, вы должны найти эти свойства визуально, отредактируйте свойства:

введите описание изображения здесь

Изменения также отражаются в пользовательских атрибутах времени выполнения:

введите описание изображения здесь

Запустите время сборки и вуаля! вы увидите четкую круглую кнопку с рамкой.

введите описание изображения здесь

Минусы Булакены
источник
Это помогло мне добиться этого в раскадровке. Ваш ответ очень понятен для реализации.
Р. Мохан
Это наиболее точный ответ на этот вопрос с четко объясненным примером.
SeaWarrior404
Если вы можете добавить для Objective-C, это будет оценено.
Михир Оза
9

Объяснение, возможно, потеряно в некоторых других ответах здесь:

Причина, по которой это свойство не устанавливается, заключается в том, что layer.borderColorтребуется значение с типом CGColor.

Но только UIColorтипы могут быть установлены через определяемые пользователем атрибуты времени выполнения Interface Builder!

Таким образом, вы должны установить UIColor для свойства прокси через Interface Builder, а затем перехватить этот вызов, чтобы установить эквивалентный CGColor для layer.borderColorсвойства.

Это может быть выполнено путем создания Категории на CALayer, установки ключевого пути на уникальное новое «свойство» ( borderColorFromUIColor) и в категории, переопределив соответствующий метод установки ( setBorderColorFromUIColor:).

пкамб
источник
1

Есть способ сделать это лучше! Вам следует использовать @IBInspectable. Посмотрите запись в блоге Майка Вулмера здесь: https://spin.atomicobject.com/2017/07/18/swift-interface-builder/

Фактически он добавляет эту функцию в IB в Xcode! Некоторые скриншоты в других ответах создают впечатление, что поля существуют в IB, но, по крайней мере, в Xcode 9 их нет. Но после его поста их добавлю.

cdeerinck
источник
Я попробовал этот подход, и это сделало Xcode очень медленным. Это происходит со всеми вами?
Meep
0

В случае Swift функция не работает. Для достижения желаемого результата вам понадобится вычисляемое свойство:

extension CALayer {
    var borderColorFromUIColor: UIColor {
        get {
            return UIColor(CGColor: self.borderColor!)
        } set {
            self.borderColor = newValue.CGColor
        }
    }
}
Фуркан Хан
источник
0

У меня это работает.

Swift 3, Xcode 8.3

Инспектор удостоверений (в данном случае UIButton

Расширение CALayer:

extension CALayer {
var borderWidthIB: NSNumber {
    get {
        return NSNumber(value: Float(borderWidth))
    }
    set {
        borderWidth = CGFloat(newValue.floatValue)
    }
}
var borderColorIB: UIColor? {
    get {
        return borderColor != nil ? UIColor(cgColor: borderColor!) : nil
    }
    set {
        borderColor = newValue?.cgColor
    }
}
var cornerRadiusIB: NSNumber {
    get {
        return NSNumber(value: Float(cornerRadius))
    }
    set {
        cornerRadius = CGFloat(newValue.floatValue)
    }
}

}

Йован Станкович
источник