Какао-дотик: як змінити колір і товщину межі 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 як __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(завдяки цьому оновлення Переглянути в прямому ефірі). *
  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 другий підхід вже не працює
Сергій Грищов

Що з об’єктивом-C?
Нік Ков

Дізнайтеся відповідь spencery2 далі нижче, він знайшов час, щоб написати його в Objective-C:
MMachinegun

оновіть розширення, щоб не зберігати значення, і використовуйте set (value) {} та отримуйте {} для доступу до шару безпосередньо, він працює тоді.
Блискавка

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. До речі, у вас є подвійний, і Кланг подасть на 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. Не перевірено, тха ...
Ніку Сурду,

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 через те, що спричинило хіт продуктивності.

Натомість я б змінив властивості класу, як показано нижче (у вашому користувальницькому uiview):

  - (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 відповідь на ціль 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 + межа:

#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

Колір межі елемента швидко в 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.