2013-08-21 16 views
11

Sto provando a creare un'etichetta (o qualsiasi altra vista per quella materia) con un angolo arrotondato e un tratto/bordo. Posso raggiungere l'ex utilizzando il seguente codice:CALayer con mascheratura a tratto in 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; 

Quali grandi opere per l'angolo arrotondato, ma utilizzando il seguente codice non si applica la corsa nel modo desiderato. Invece di produrre un nero (o qualunque sia il backgroundColor di self.label impostato su) confine quadrato.

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; 

Qualche suggerimento su come applicare un tratto colorato arbitrario che segue il percorso mascherato?

risposta

35

Sei sulla strada giusta con il livello di forma. Ma dovresti avere due livelli diversi. Prima il livello maschera come nel primo esempio che maschera la vista (taglia le aree che non si desidera essere visibili)

Quindi si aggiunge anche lo strato forma, ma non come livello maschera. Inoltre, assicurati di non utilizzare borderWidth e borderColor, ma tratti.

// 
// 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]; 

Tenere presente che il percorso del tratto di tratto deve essere all'interno (minore del) del percorso della maschera. Altrimenti, il percorso tracciato verrà mascherato dal livello maschera. Ho impostato la riga con 3, che consente di vedere la metà della larghezza (1,5 px) e l'altra metà all'esterno della maschera.

+0

Questo genere di opere, ma ora il il testo dell'etichetta è stato coperto dal livello 'shape' :( –

+1

OK Sono riuscito a farlo funzionare applicando la maschera ad un' UIView' e aggiungendo il 'UILabel' come sottoview.Grazie mille :) –

+8

StrokeLayer copre l'etichetta quindi l'ho aggiunta per risolvere il problema 'shape.fillColor = [UIColor clearColor] .CGColor' –

0

Se si sottoclasse CALayer, è possibile creare un'istanza con la maschera desiderata e anche sostituire layoutSubLayers per includere il bordo desiderato su quella maschera.

Potrebbe fare un paio di modi. Sotto Ill lo si utilizza utilizzando lo path della maschera specificata e assegnandolo alla proprietà di classe da utilizzare per la costruzione del nuovo bordo in layoutSubLayers. Esiste la possibilità che questo metodo possa essere chiamato più volte, quindi ho anche impostato un valore booleano per tracciarlo. (Potrebbe anche assegnare il confine come una proprietà di classe, e rimuovere/aggiungere nuovamente ogni volta Per il momento, io uso assegno 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") 
    } 
}