2013-03-03 25 views
60

Nếu thêm một biên giới một cái nhìn sử dụng mã trong một cái nhìn nhưThêm một biên giới bên ngoài của một UIView (thay vì bên trong)

self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = 2.0f; 

biên giới được thêm vào bên trong xem như sau: enter image description here

chế độ xem phù hợp là chế độ xem gốc, như bạn có thể thấy, khu vực màu đen của chế độ xem có biên giới nhỏ hơn chế độ xem ban đầu. nhưng điều tôi muốn có là đường viền nằm ngoài khung nhìn gốc, như sau: enter image description here. vùng màu đen bằng với vùng gốc, làm thế nào tôi có thể thực hiện nó?

Trả lời

83

Thật không may, không chỉ đơn giản là một chút tài sản mà bạn có thể thiết lập để sắp xếp biên giới với bên ngoài. Nó vẽ liên kết với bên trong vì các hoạt động vẽ mặc định của UIViews vẽ trong giới hạn của nó.

Giải pháp đơn giản nhất mà nói đến cái tâm sẽ được mở rộng UIView bởi kích thước của chiều rộng biên giới khi áp dụng biên giới:

CGFloat borderWidth = 2.0f; 

self.frame = CGRectInset(self.frame, -borderWidth, -borderWidth); 
self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = borderWidth; 
+0

Tôi đã sử dụng này trên quan điểm của UITableViewCell. nhưng trên dòng, self.frame = CGRectInset (self.frame, -borderWidth, -borderWidth); Chiều rộng và chiều cao của chế độ xem tiếp tục tăng nếu chúng tôi tiếp tục cuộn bảng xem .. Vì vậy, tôi đã kết thúc bằng cách xóa nó. – Neela

+0

Phương pháp này tiếp tục tăng chiều cao xem để tôi xóa mã này và sử dụng mã sau self.view.layer.borderColor = [[Màu UIColorWithRed: 209.0f/255.0f màu xanh lá cây: 33.0f/255.0f màu xanh: 8.0f/255.0 f alpha: 1.0f] CGColor]; self.view.layer.borderWidth = 1.0f; –

+2

Cố gắng giải pháp này trong Swift, không làm việc không may, biên giới tiếp tục vẽ bên trong UIImageView – DCDC

1

Tăng chiều rộng và chiều cao của khung nhìn với chiều rộng biên giới trước khi thêm biên giới:

float borderWidth = 2.0f 
CGRect frame = self.frame; 
frame.width += borderWidth; 
frame.height += borderWidth; 
self.layer.borderColor = [UIColor yellowColor].CGColor; 
self.layer.borderWidth = 2.0f; 
12

Vâng không có phương pháp trực tiếp để làm điều đó Bạn có thể xem xét một số cách giải quyết.

  1. Thay đổi và tăng khung và thêm bordercolor như bạn đã làm
  2. Thêm một cái nhìn đằng sau giao diện hiện tại với kích thước lớn hơn để nó xuất hiện như border.Can được làm việc như một lớp tùy chỉnh của xem
  3. Nếu bạn không cần một biên giới rõ ràng (biên giới cắt ngắn) sau đó bạn có thể phụ thuộc vào bóng cho mục đích này

    [view1 setBackgroundColor:[UIColor blackColor]]; 
    UIColor *color = [UIColor yellowColor]; 
    view1.layer.shadowColor = [color CGColor]; 
    view1.layer.shadowRadius = 10.0f; 
    view1.layer.shadowOpacity = 1; 
    view1.layer.shadowOffset = CGSizeZero; 
    view1.layer.masksToBounds = NO; 
    
13

Ok, đã có một chấp nhận câu trả lời nhưng tôi nghĩ rằng có một cách tốt hơn để làm điều đó, bạn chỉ cần có một lớp mới lớn hơn một chút so với quan điểm của bạn và không che giấu nó vào các giới hạn của lớp xem (mà thực sự là hành vi mặc định). Đây là đoạn mã mẫu:

CALayer * externalBorder = [CALayer layer]; 
externalBorder.frame = CGRectMake(-1, -1, myView.frame.size.width+2, myView.frame.size.height+2); 
externalBorder.borderColor = [UIColor blackColor].CGColor; 
externalBorder.borderWidth = 1.0; 

[myView.layer addSublayer:externalBorder]; 
myView.layer.masksToBounds = NO; 

Tất nhiên đây là nếu bạn muốn biên giới của bạn sẽ được 1 đoàn lớn, nếu bạn muốn biết thêm bạn thích ứng với borderWidth và khung của lớp cho phù hợp. này là tốt hơn so với sử dụng một cái nhìn thứ hai lớn hơn một chút như một CALayer nhẹ hơn một UIView và bạn không cần phải làm thay đổi khung myView, đó là tốt ví dụ nếu myView là một NB UIImageView

: Đối với tôi kết quả không hoàn hảo trên mô phỏng (lớp không chính xác ở đúng vị trí sao cho lớp dày hơn ở một bên đôi khi) nhưng chính xác là những gì được yêu cầu trên thiết bị thực.

EDIT

Trên thực tế vấn đề tôi nói về trong N.B là chỉ vì tôi đã giảm màn hình của mô phỏng, trên kích thước bình thường có là hoàn toàn không có vấn đề

Hy vọng nó giúp

+0

myView.layer.masksToBounds = KHÔNG; nó đang tạo ra vấn đề khi myView có CornerRadius. – umakanta

7

Đối với việc thực hiện Swift, bạn có thể thêm này như một phần mở rộng UIView.

extension UIView { 

    struct Constants { 
     static let ExternalBorderName = "externalBorder" 
    } 

    func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.whiteColor()) -> CALayer { 
     let externalBorder = CALayer() 
     externalBorder.frame = CGRectMake(-borderWidth, -borderWidth, frame.size.width + 2 * borderWidth, frame.size.height + 2 * borderWidth) 
     externalBorder.borderColor = borderColor.CGColor 
     externalBorder.borderWidth = borderWidth 
     externalBorder.name = Constants.ExternalBorderName 

     layer.insertSublayer(externalBorder, atIndex: 0) 
     layer.masksToBounds = false 

     return externalBorder 
    } 

    func removeExternalBorders() { 
     layer.sublayers?.filter() { $0.name == Constants.ExternalBorderName }.forEach() { 
      $0.removeFromSuperlayer() 
     } 
    } 

    func removeExternalBorder(externalBorder: CALayer) { 
     guard externalBorder.name == Constants.ExternalBorderName else { return } 
     externalBorder.removeFromSuperlayer() 
    } 

} 
+0

Tuyệt vời! Cảm ơn bạn! Một số điều được thay đổi trong Swift 4 và bây giờ trông khác nhau, nhưng Xcode giải thích cách sửa đổi mã. Và trong phương thức 'removeExternalBorder' phải là 'guard externalBorder.name =='. – DmitryKanunnikoff

2

Với trên chấp nhận câu trả lời tốt nhất tôi đã làm kinh nghiệm với các ví dụ không đẹp kết quả và cạnh khó coi:

border without bezier path

Vì vậy, tôi sẽ chia sẻ UIView tôi Swift mở rộng với bạn, rằng sử dụng UIBezierPath thay vì đường viền biên giới - không có cạnh khó coi (lấy cảm hứng từ @Fattie):

border with bezier path

// UIView+BezierPathBorder.swift 

import UIKit 

extension UIView { 

    fileprivate var bezierPathIdentifier:String { return "bezierPathBorderLayer" } 

    fileprivate var bezierPathBorder:CAShapeLayer? { 
     return (self.layer.sublayers?.filter({ (layer) -> Bool in 
      return layer.name == self.bezierPathIdentifier && (layer as? CAShapeLayer) != nil 
     }) as? [CAShapeLayer])?.first 
    } 

    func bezierPathBorder(_ color:UIColor = .white, width:CGFloat = 1) { 

     var border = self.bezierPathBorder 
     let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:self.layer.cornerRadius) 
     let mask = CAShapeLayer() 
     mask.path = path.cgPath 
     self.layer.mask = mask 

     if (border == nil) { 
      border = CAShapeLayer() 
      border!.name = self.bezierPathIdentifier 
      self.layer.addSublayer(border!) 
     } 

     border!.frame = self.bounds 
     let pathUsingCorrectInsetIfAny = 
      UIBezierPath(roundedRect: border!.bounds, cornerRadius:self.layer.cornerRadius) 

     border!.path = pathUsingCorrectInsetIfAny.cgPath 
     border!.fillColor = UIColor.clear.cgColor 
     border!.strokeColor = color.cgColor 
     border!.lineWidth = width * 2 
    } 

    func removeBezierPathBorder() { 
     self.layer.mask = nil 
     self.bezierPathBorder?.removeFromSuperlayer() 
    } 

} 

Ví dụ:

let view = UIView(frame: CGRect(x: 20, y: 20, width: 100, height: 100)) 
view.layer.cornerRadius = view.frame.width/2 
view.backgroundColor = .red 

//add white 2 pixel border outline 
view.bezierPathBorder(.white, width: 2) 

//remove border outline (optional) 
view.removeBezierPathBorder() 
Các vấn đề liên quan