2011-08-26 19 views
11

Próbuję dodać warstwę gradientu do mojego UILabel z niektórych powodów, dla których CAGradientLayer obejmuje mój tekst. robię niczego złegoCel C - CAGradientLayer obejmuje tekst w 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]; 
} 

Odpowiedz

12

CAGradientLayer zasłania tekst etykiety, ponieważ tekst jest zasysane przez zawartość super warstwy jawnie objętych dodanie podwarstwy.

Najprostszym rozwiązaniem jest użycie dwóch widoków. Podklasa UIView, w której zastępujesz +[UIView layerClass] i zwracasz [CAGradientLayer]. Dodaj dobrą metodę init do ustawienia gradientu.

Następna osoba dodaje UILabel jako widok niestandardowego widoku gradientowego.

+0

Jako na boku i z ciekawości na temat konkretnej implementacji, którą akceptuję, byłoby bardzo kiepskim pomysłem, na którym można polegać, nawet jeśli jest ona znana; Nie sprawdziłem, ale przypuszczam, że UILabel używa CATextLayer od jego dostępności w systemie iOS 3.2? – Tommy

+0

@Tommy - 'UILabel' nie jest wspierany przez' CATextLayer' przed lub po wersji 3.2. Możesz to łatwo sprawdzić za pomocą "' po [[someLabel layer] class] '", która da podstawową 'CALayer'. Jest to również bardzo widoczne, ponieważ 'CATextLayer' nie ma podosiowego antyaliasingu, ale' UILabel' robi. – PeyloW

+0

Typ klasy nie zawsze jest pouczający, jak każdy, kto kiedykolwiek próbował [str isKindOfClass: [NSMutableString class]] może potwierdzić. Jest to kwestia pomostowa i oczywiście CALayer nie jest oficjalnie wolny od mostów z niczym, ale założenie, że nie ma podobnego klastrowania klas ani aliasingu w CALayer, jest właśnie tym: założeniem. Rozumiem, że podpunktowy wskaźnik antyaliasingu jest dość definitywny. – Tommy

0

Miałem ten sam problem. Zrobiłem tę metodę, aby uzyskać odniesienie do warstwy kształtu i lub wygenerować ją, jeśli jej tam nie było. Ta metoda powoduje, że warstwa ta jest rzucana z tyłu, dzięki czemu nie pokrywa ona warstwy tekstu etykiety. Po prostu użyj tego i powinieneś być dobry, bez dodatkowych podklas wymaganych.

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

Jeśli na przykład trzeba podklasy swoją UILabel, następnie dodać trochę CALayer obejmujący tekst, zaleca się, aby dodać CATextLayer do CALayer, tutaj jest szybki przykład:

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