2013-08-21 10 views
11

Tôi đang cố tạo nhãn (hoặc bất kỳ chế độ xem nào khác cho vấn đề đó) với một góc tròn và đường viền/đường viền. Tôi có thể đạt được bằng cách sử dụng mã sau đây:Stroke đeo mặt nạ CALayer trong iOS

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds 
             byRoundingCorners:UIRectCornerBottomRight 
              cornerRadii:CGSizeMake(16.0f, 16.0f)]; 

CAShapeLayer *shape = [CAShapeLayer layer]; 
shape.frame = self.label.bounds; 
shape.path = maskPath.CGPath; 

self.label.layer.mask = shape; 

Công trình nào tuyệt vời cho góc tròn, nhưng sử dụng mã sau không áp dụng theo cách tôi muốn. Thay vào đó, hãy tạo màu đen (hoặc bất kỳ số nào là backgroundColor của self.label được đặt thành) vuông đường viền.

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds 
             byRoundingCorners:UIRectCornerBottomRight 
              cornerRadii:CGSizeMake(16.0f, 16.0f)]; 

CAShapeLayer *shape = [CAShapeLayer layer]; 
shape.frame = self.label.bounds; 
shape.path = maskPath.CGPath; 

// Add stroke 
shape.borderWidth = 1.0f; 
shape.borderColor = [UIColor whiteColor].CGColor; 

self.label.backgroundColor = [UIColor blackColor]; 
self.label.layer.mask = shape; 

Bất kỳ đề xuất nào về cách tôi có thể áp dụng nét màu tùy ý theo đường dẫn được che dấu?

Trả lời

35

Bạn đang đi đúng hướng với lớp hình dạng. Nhưng bạn nên có hai lớp khác nhau. Đầu tiên là lớp mặt nạ như trong ví dụ đầu tiên che giấu tầm nhìn của bạn (cắt các vùng bạn không muốn hiển thị)

Sau đó, bạn thêm lớp hình dạng, nhưng không phải là lớp mặt nạ. Ngoài ra, hãy chắc chắn không sử dụng borderWidth và borderColor, nhưng đột quỵ.

// 
// Create your mask first 
// 
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds 
             byRoundingCorners:UIRectCornerBottomRight 
              cornerRadii:CGSizeMake(16.0f, 16.0f)]; 

CAShapeLayer *maskLayer = [CAShapeLayer layer]; 
maskLayer.frame = self.label.bounds; 
maskLayer.path = maskPath.CGPath; 
self.label.layer.mask = maskLayer;  

// 
// And then create the outline layer 
// 
CAShapeLayer *shape = [CAShapeLayer layer]; 
shape.frame = self.label.bounds; 
shape.path = maskPath.CGPath; 
shape.lineWidth = 3.0f; 
shape.strokeColor = [UIColor whiteColor].CGColor; 
shape.fillColor = [UIColor clearColor].CGColor; 
[self.label.layer addSublayer:shape]; 

Lưu ý rằng đường dẫn lớp nét vẽ của bạn phải ở trong (nhỏ hơn) đường dẫn của mặt nạ. Nếu không, đường nét được vuốt sẽ bị che đi bởi lớp mặt nạ. Tôi đã thiết lập lineWith đến 3 mà làm cho nó để bạn có thể thấy một nửa chiều rộng (1,5 px), và một nửa khác sẽ được bên ngoài mặt nạ.

+0

loại Đó là công trình nhưng bây giờ văn bản của nhãn đã được bao phủ bởi lớp 'shape': ( –

+1

OK) Tôi đã quản lý để làm cho nó hoạt động bằng cách áp dụng mặt nạ cho một' UIView' và thêm 'UILabel' như là một subview. Cảm ơn rất nhiều :) –

+8

StrokeLayer bao gồm nhãn vì vậy tôi đã thêm điều này để sửa lỗi đó lên 'shape.fillColor = [UIColor clearColor] .CGColor' –

0

Nếu bạn phân lớp CALayer, bạn có thể khởi tạo nó bằng mặt nạ bạn muốn và cũng ghi đè layoutSubLayers để bao gồm đường viền bạn muốn trên mặt nạ đó.

Có thể thực hiện việc này theo một vài cách. Bên dưới Ill làm điều đó bằng cách sử dụng path của mặt nạ đã cho và gán nó cho thuộc tính lớp được sử dụng để tạo đường viền mới trong layoutSubLayers. Có khả năng rằng phương pháp này có thể được gọi nhiều lần, vì vậy tôi cũng thiết lập một boolean để theo dõi này. (Cũng có thể gán biên giới như một thuộc tính lớp, và gỡ bỏ/tái thêm mỗi lần Còn bây giờ, tôi sử dụng kiểm tra bool

Swift 3:..

class CustomLayer: CALayer { 

    private var path: CGPath? 
    private var borderSet: Bool = false 

    init(maskLayer: CAShapeLayer) { 
     super.init() 
     self.path = maskLayer.path 
     self.frame = maskLayer.frame 
     self.bounds = maskLayer.bounds 
     self.mask = maskLayer 
    } 

    override func layoutSublayers() { 

     let newBorder = CAShapeLayer() 

     newBorder.lineWidth = 12 
     newBorder.path = self.path 
     newBorder.strokeColor = UIColor.black.cgColor 
     newBorder.fillColor = nil 


     if(!borderSet) { 
      self.addSublayer(newBorder) 
      self.borderSet = true 
     } 

    } 

    required override init(layer: Any) { 
     super.init(layer: layer) 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
}