Какао 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каждый раз. Однако одним из недостатков этого является то, что вы увидите свои изменения только при запуске приложения.


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 ...
Нику Сурду



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 останавливает это ;-)


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

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

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.