2011-08-26 9 views
11

Sto tentando di aggiungere un gradiente di gradazioni al mio UILabel per alcuni motivi il CAGradientLayer copre il mio testo. Sto facendo qualcosa di sbagliatoObjective C - CAGradientLayer copre il testo in UILabel?

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    CAGradientLayer *gradient = [CAGradientLayer layer]; 
    gradient.frame = CGRectMake(0, 0, myLabel.frame.size.width, myLabel.frame.size.height); 
    gradient.colors = myColors; 
    [myLabel.layer insertSublayer:gradient atIndex:0]; 
} 

risposta

12

Il CAGradientLayer sta coprendo il testo dell'etichetta perché il testo è tratto dal contenuto dello strato super-che espressamente trattati con l'aggiunta di un sottolivello.

La soluzione più semplice è utilizzare due viste. Una sottoclasse UIView in cui si esegue l'override di +[UIView layerClass] e si restituisce un [CAGradientLayer]. Aggiungi un buon metodo init per impostare il tuo gradiente.

Il prossimo cucciolo aggiunge lo UILabel come visualizzazione secondaria della vista sfumatura personalizzata.

+0

Come a parte e per curiosità su una specifica implementazione che accetto sarebbe una pessima idea su cui contare anche se conosciuto; Non ho controllato, ma presumibilmente UILabel utilizza un CATextLayer come la sua disponibilità in iOS 3.2? – Tommy

+0

@Tommy - 'UILabel' non è supportato da un' CATextLayer' prima o dopo 3.2. Puoi facilmente ispezionarlo con "classe' po [[someLabel layer]] "che produrrà un' CALayer' di base. È anche abbastanza visivamente evidente dal momento che 'CATextLayer' non ha antialiasing subpixel ma' UILabel' fa. – PeyloW

+0

Tuttavia, il tipo di classe non è sempre istruttivo, come chiunque abbia mai provato [str isKindOfClass: [NSMutableString class]] può attestare. Questo è un problema di bridging e ovviamente CALayer non è ufficialmente collegato a nessun ponte, ma non assumere alcun cluster di classe simile o aliasing all'interno di CALayer è solo questo: un'ipotesi. Prendo atto del fatto che l'indizio antialiasing subpixel è abbastanza definitivo. – Tommy

0

Ho avuto lo stesso problema. Ho creato questo metodo per ottenere un riferimento per il livello forma e per generarlo se non fosse presente. Questo metodo fa in modo di gettare quel livello nella parte posteriore in modo che non copra il livello del testo dell'etichetta. Basta usare questo e si dovrebbe essere tutto buono, non sono richieste sottoclassi extra.

- (CAShapeLayer*) getShapeLayerForObject: (UIView*) object{ 
    CAShapeLayer *maskLayer; 
    int loc = -1; 
    for(int x = 0; x < object.layer.sublayers.count; x++){ 
     if([[object.layer.sublayers objectAtIndex:x] isKindOfClass:[CAShapeLayer class]]){ 
      loc = x; 
      break; 
     } 
    } 
    if(loc > -1){ 
     maskLayer = (CAShapeLayer*) [object.layer.sublayers objectAtIndex:loc]; 
    }else{ 
     maskLayer = [[CAShapeLayer alloc] init]; 
     [object.layer insertSublayer:maskLayer atIndex:0]; 

    } 
    return maskLayer; 
} 
0

Se per esempio bisogno di sottoclasse vostra UILabel, quindi aggiungere un po 'di CALayer che copre il testo, si consiglia di aggiungere CATextLayer al vostro CALayer, ecco un esempio veloce:

@IBDesignable class BWRoundedLabel: UILabel { 

    override var text: String? { 
     didSet { 
      updateView() 
     } 
    } 

    @IBInspectable override var shadowColor: UIColor? { 

     didSet { 
      updateView() 
     } 
    } 

    private func updateView() { 

     let width = bounds.size.width - 1 
     let height = bounds.size.height - 1 

     let shadowLayer = CAShapeLayer() 
     shadowLayer.path = UIBezierPath(roundedRect: CGRectMake(0, 0, width, height), cornerRadius: width/2).CGPath 
     shadowLayer.fillColor = UIColor.yellowOrange().CGColor 
     shadowLayer.shadowColor = shadowColor?.CGColor 
     shadowLayer.shadowPath = shadowLayer.path 
     shadowLayer.shadowOffset = CGSize(width: 0, height: 1.0) 
     shadowLayer.shadowOpacity = 1 
     shadowLayer.shadowRadius = 0 

     let textLayer = CATextLayer() 
     textLayer.foregroundColor = UIColor.whiteColor().CGColor 
     textLayer.string = text 
     textLayer.fontSize = font.pointSize 
     textLayer.font = "Calibri-Bold" 
     textLayer.alignmentMode = kCAAlignmentCenter 
     textLayer.frame = CGRectMake(0, (height - 16)/2, width, 16) 

     if let sublayers = layer.sublayers { 
      for sublayer in sublayers { 
       sublayer.removeFromSuperlayer() 
      } 
     } 

     layer.insertSublayer(shadowLayer, atIndex: 0) 
     layer.insertSublayer(textLayer, atIndex: 1) 
    } 
}