Какао Touch: Как изменить цвет и толщину границы UIView?

Ответы:

596

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

#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;

Вам также нужно связаться с QuartzCore.framework для доступа к этой функции.

Владимир
источник
Есть ли способ установить разные ширины / цвета для каждой стороны?
lluismontero
2
@lluismontero Боюсь, вам придется сделать пользовательский UIView с drawRect: метод для этого
Владимир
1
Если я сделаю это, и поверх этого представления у меня будет анимация, например, модальное отклонение UINavigationController, я вижу, что происходит много глюков, это трудно описать. Если я деактивирую границы, все возвращается на круги своя.
Нику Сурду
5
Просто головы для других. Xcode предлагает соединить UIColor с CGColorRef as __bridge CGColorRef. Это не работает. Это должно быть [UIColor blackColor].CGColorкак указано в ответе.
GoodSp33d
6
#import <QuartzCore/QuartzCore.h>больше не нужен.
значение имеет значение
43

Xcode 6 обновление

Начиная с последней версии XCode, есть лучшее решение для этого:

С @IBInspectableвы можете установить атрибуты непосредственно из внутриAttributes Inspector .

Мой пользовательский вид @IBInspectable Attributes

Это устанавливает User Defined Runtime Attributesдля вас:

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

Есть два подхода к настройке:

Вариант 1 (с живым обновлением в раскадровке)

  1. Создать MyCustomView.
  2. Это наследуется от UIView.
  3. Установить @IBDesignable(это делает обновление View активным). *
  4. Установите свои атрибуты времени выполнения (границы и т. Д.) С помощью @IBInspectable
  5. Измените класс просмотров на MyCustomView
  6. Отредактируйте в панели атрибутов и посмотрите изменения в раскадровке :)

`

@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

* @IBDesignableработает только при установке в началеclass MyCustomView

Вариант 2 (не работает с Swift 1.2, см. Комментарии)

Расширьте свой класс UIView:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

Таким образом, ваш вид по умолчанию всегда содержит эти дополнительные редактируемые поля Attributes Inspector. Еще одним преимуществом является то, что вам не нужно менять класс MycustomViewкаждый раз. Однако одним из недостатков этого является то, что вы увидите свои изменения только при запуске приложения.

MMachinegun
источник
1
Ваше расширение не работает в последней версии XCode на сегодняшний день.
Эдгар Арутюнян
1
Я подтвердлю @EdgarAroutiounian только для того, чтобы сказать, что в Swift 1.2 второй подход больше не работает
Сергей Грищев
Как насчет Objective-C?
Ник Ков
Посмотрите ответ spencery2 ниже, он нашел время написать его в Objective-C:
MMachinegun
обновите расширение, чтобы оно не сохраняло значение, и используйте set (value) {} и get {} для прямого доступа к слою, тогда оно работает.
LightningStryk
17

Вы также можете создать рамку с цветом вашего желания.

view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;

* r, g, b - значения от 0 до 255.

Роган-патель
источник
6
Стоит отметить , что r, gи , bвероятно , следует поплавки; делители тоже должны быть поплавками r / 255.0.
нет, синтаксис C не такой, как Вы говорите. r, g и b могут быть int, так как при продвижении C (и objC IS C) int r = 128 удваивается при создании: r / 255.0. Кстати, у вас есть двойной, и Clang будет разыгрывать CGFloat.
ingconti
10

Добавьте следующие @IBInspectables в расширение UIView

extension UIView {

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

  @IBInspectable var borderColor: UIColor? {
    get {
      if let color = layer.borderColor {
        return UIColor(CGColor: color)
      }
      return nil
    }
    set(newValue) {
      layer.borderColor = newValue?.CGColor
    }
  }
}

И тогда вы сможете установить атрибуты borderColor и borderWidth непосредственно из инспектора атрибутов. Смотрите прикрепленное изображение

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

Бикрамджит Сингх
источник
8

Когда я использую решение CALayer Владимира, и в верхней части представления у меня есть анимация, например, модальное отключение UINavigationController, я вижу, что происходит много глюков и возникают проблемы с производительностью при рисовании.

Итак, еще один способ добиться этого, но без сбоев и потери производительности, - создать пользовательский UIView и реализовать drawRectсообщение следующим образом:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}
Нику Сурду
источник
@Krish Вы сохраняете цвет в переменной, а когда вам нужно изменить цвет границы, вы изменяете значение переменной и вызываете setNeedsDisplayпредставление. Это заставит перерисовать UIView и неявно перезвонит drawRect. Не проверено, tho ...
Нику Сурду
8
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
Шейджу Мэтью
источник
1
Мне действительно не нравится, когда людей голосуют без объяснения причин. Это никому не помогает.
Дэвид ДелМонте
7

Попробуйте этот код:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
Викрам Бивал
источник
4

Я бы не советовал переопределять drawRect из-за снижения производительности.

Вместо этого я бы изменил свойства класса, как показано ниже (в вашем пользовательском интерфейсе):

  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
    }
  return self;

Я не видел никаких глюков при использовании вышеупомянутого подхода - не уверен, почему включение initWithFrame останавливает это ;-)

DEzra
источник
3

Я хотел добавить это к ответу @ marczking ( вариант 1 ) в качестве комментария, но мой скромный статус в StackOverflow препятствует этому.

Я сделал ответ @ marczking на Objective C. Работает как шарм, спасибо @marczking!

UIView + Border.h:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface UIView (Border)

-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;

@end

UIView + Border.m:

#import "UIView+Border.h"

@implementation UIView (Border)
// Note: cannot use synthesize in a Category

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

-(void)setBorderWidth:(CGFloat)width
{
    self.layer.borderWidth = width;
}

-(void)setCornerRadius:(CGFloat)radius
{
    self.layer.cornerRadius = radius;
    self.layer.masksToBounds = radius > 0;
}

@end
spencery2
источник
2

@IBInspectable работает для меня на iOS 9, Swift 2.0

extension UIView {

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

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

@IBInspectable var borderColor: UIColor? {
    get {
        if let color = layer.borderColor {
            return UIColor(CGColor: color)
        }
        return nil
    }
    set(newValue) {
        layer.borderColor = newValue?.CGColor
    }
}
anhtran
источник
1

Если вы не хотите редактировать слой UIView, вы всегда можете встроить представление в другое представление. В родительском представлении цвет фона будет установлен на цвет границы. Это также будет немного больше, в зависимости от ширины границы.

Конечно, это работает только в том случае, если ваш вид не прозрачен и вам нужен только один цвет рамки. ФП хотел иметь границу в самом представлении, но это может быть жизнеспособной альтернативой.

Мэтт Беккер
источник
0

Если вы хотите добавить разные границы на разных сторонах, возможно, добавьте подпредставление с определенным стилем, способ легко придумать.

Юаньфей Чжу
источник
0

Цвет границы элемента в Swift 4.2:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
Akhrua
источник