Ca cao cảm ứng: Làm thế nào để thay đổi màu viền và độ dày của UIView?


Câu trả lời:


596

Bạn cần sử dụng lớp của view để đặt thuộc tính viền. ví dụ:

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

Bạn cũng cần liên kết với QuartzCore.framework để truy cập chức năng này.


Có cách nào để thiết lập chiều rộng / màu sắc khác nhau cho mỗi bên không?
lluismontero

2
@lluismontero Tôi e rằng bạn sẽ phải tạo UIView tùy chỉnh với drawRect: phương thức cho điều đó
Vladimir

1
Nếu tôi làm điều này, và trên quan điểm này, tôi có một hình ảnh động, giống như một chế độ UINavestionControll bị loại bỏ, tôi thấy rất nhiều trục trặc xảy ra, thật khó để diễn tả. Nếu tôi hủy kích hoạt đường viền, mọi thứ sẽ trở lại bình thường.
Nicu Surdu

5
Chỉ cần một đầu lên cho người khác. Xcode đề xuất bắc cầu UIColor sang CGColorRef như __bridge CGColorRef. Điều này không hoạt động. Nó cần phải được [UIColor blackColor].CGColorđề cập trong câu trả lời.
GoodSp33d

6
#import <QuartzCore/QuartzCore.h>không còn cần thiết.
ý nghĩa-vấn đề

43

Cập nhật Xcode 6

Vì phiên bản mới nhất của Xcode, có một giải pháp tốt hơn cho vấn đề này:

Với @IBInspectablebạn có thể thiết lập thuộc tính trực tiếp từ bên trong các Attributes Inspector.

Chế độ xem tùy chỉnh của tôi @IBInspectable Attribution

Điều này đặt ra User Defined Runtime Attributescho bạn:

nhập mô tả hình ảnh ở đây

Có hai cách tiếp cận để thiết lập điều này:

Tùy chọn 1 (có cập nhật trực tiếp trong Storyboard)

  1. Tạo MyCustomView.
  2. Điều này kế thừa từ UIView.
  3. Đặt @IBDesignable(điều này làm cho bản cập nhật Xem trực tiếp). *
  4. Đặt thuộc tính thời gian chạy của bạn (viền, v.v.) với @IBInspectable
  5. Thay đổi lớp Lượt xem của bạn thành MyCustomView
  6. Chỉnh sửa trong Bảng thuộc tính và xem các thay đổi trong Bảng phân cảnh :)

`

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

* @IBDesignablechỉ hoạt động khi được đặt ở đầuclass MyCustomView

Tùy chọn 2 (không hoạt động kể từ Swift 1.2, xem bình luận)

Mở rộng Lớp UIView của bạn:

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

Bằng cách này, Chế độ xem mặc định của bạn luôn có các trường có thể chỉnh sửa thêm đó Attributes Inspector. Một lợi thế khác là bạn không phải thay đổi lớp MycustomViewmỗi lần. Tuy nhiên, một nhược điểm của điều này là bạn sẽ chỉ thấy những thay đổi của mình khi chạy ứng dụng.


1
Tiện ích mở rộng của bạn không hoạt động trong phiên bản Xcode mới nhất tính đến ngày hôm nay.
Edgar Aroutiounian

1
Tôi sẽ xác nhận @EdgarAroutiounian chỉ để nói rằng trong Swift 1.2, cách tiếp cận thứ hai không còn hiệu quả nữa
Serge Grischyov

Còn Objective-C thì sao?
Nik Kov

Kiểm tra câu trả lời của spencery2 bên dưới, anh ấy đã dành thời gian để viết nó trong Objective-C:
MMachinegun

cập nhật tiện ích mở rộng để không lưu trữ giá trị và sử dụng set (value) {} và lấy {} để truy cập trực tiếp vào lớp, nó hoạt động sau đó.
LightningStryk

17

Bạn cũng có thể tạo đường viền với màu của điều ước của bạn ..

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

* r, g, b là các giá trị trong khoảng từ 0 đến 255.


6
Điều đáng chú ý là r, gbcó lẽ nên là phao; các ước số cũng phải là float : r / 255.0.

không, cú pháp C không như bạn nói. r, g và b có thể là int, vì các chương trình khuyến mãi C (và objC IS C) sẽ chuyển int r = 128 lên gấp đôi khi thực hiện: r / 255.0. Nhân tiện, bạn đã nhân đôi và Clang sẽ chuyển sang CGFloat.
ingconti

10

Thêm @IBInspectables trong phần mở rộng 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
    }
  }
}

Và sau đó, bạn sẽ có thể đặt các thuộc tính BorderColor và BorderWidth trực tiếp từ trình kiểm tra thuộc tính. Xem hình ảnh đính kèm

Thanh tra thuộc tính


8

Khi tôi sử dụng giải pháp CALayer của Vladimir và trên đỉnh của chế độ xem tôi có một hình ảnh động, giống như một chế độ UINavestionControll bị loại bỏ, tôi thấy rất nhiều trục trặc xảy ra và có vấn đề về hiệu năng.

Vì vậy, một cách khác để đạt được điều này, nhưng không có trục trặc và mất hiệu suất, là tạo một UIView tùy chỉnh và thực hiện drawRectthông báo như vậy:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}

@Krish Bạn lưu trữ màu trong một biến và khi bạn cần thay đổi màu đường viền, bạn thay đổi giá trị biến và gọi setNeedsDisplaytrên màn hình. Điều này sẽ buộc vẽ lại UIView và ngầm gọi lại drawRect. Chưa được thử nghiệm, tho ...
Nicu Surdu

8
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor

1
Tôi thực sự không thích mọi người bỏ phiếu mà không có lời giải thích. Nó giúp không ai cả.
David DelMonte

7

Hãy thử mã này:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];

4

Tôi sẽ không đề xuất ghi đè drawRect do gây ra hiệu suất.

Thay vào đó, tôi sẽ sửa đổi các thuộc tính của lớp như bên dưới (trong uiview tùy chỉnh của bạn):

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

Tôi đã không thấy bất kỳ trục trặc nào khi thực hiện phương pháp trên - không chắc tại sao việc đưa vào initWithFrame lại ngăn chặn những điều này ;-)


3

Tôi muốn thêm câu này vào câu trả lời của @ marczking ( Tùy chọn 1 ) dưới dạng nhận xét, nhưng trạng thái thấp của tôi trên StackOverflow đang ngăn chặn điều đó.

Tôi đã thực hiện một câu trả lời của @ marczking cho Objective C. Hoạt động như sự quyến rũ, cảm ơn @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 đang hoạt động với tôi trên 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

Nếu bạn không muốn chỉnh sửa lớp của UIView, bạn luôn có thể nhúng chế độ xem trong chế độ xem khác. Chế độ xem chính sẽ có màu nền được đặt thành màu viền. Nó cũng sẽ lớn hơn một chút, tùy thuộc vào độ rộng bạn muốn đường viền.

Tất nhiên, điều này chỉ hoạt động nếu chế độ xem của bạn không trong suốt và bạn chỉ muốn một màu viền duy nhất. OP muốn có đường viền trong chế độ xem, nhưng đây có thể là một sự thay thế khả thi.


0

Nếu bạn muốn thêm các đường viền khác nhau ở các mặt khác nhau, có thể thêm một khung nhìn phụ với kiểu cụ thể là một cách dễ dàng để đưa ra.


0

màu đường viền của vật phẩm trong 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.