Objective C - CAGradientLayer 覆盖 UILabel 中的文本?

Posted

技术标签:

【中文标题】Objective C - CAGradientLayer 覆盖 UILabel 中的文本?【英文标题】:Objective C - CAGradientLayer covers the text in UILabel? 【发布时间】:2011-08-26 19:05:32 【问题描述】:

由于某些原因,CAGradientLayer 覆盖了我的文本,我正在尝试将渐变层添加到我的 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];

【问题讨论】:

【参考方案1】:

CAGradientLayer 覆盖了标签的文本,因为文本是由您通过添加子层明确覆盖的超级层的内容绘制的。

您最简单的解决方案是使用两个视图。 UIView 子类,您可以在其中覆盖 +[UIView layerClass] 并返回 [CAGradientLayer]。添加一个好的初始化方法来设置你的渐变。

下一个小狗将UILabel 添加为自定义渐变视图的子视图。

【讨论】:

顺便说一句,出于对特定实现的好奇,我接受即使已知,依赖它也是一个非常糟糕的主意;我还没有检查,但大概 UILabel 使用 CATextLayer,因为它在 ios 3.2 中的可用性? @Tommy - UILabel 在 3.2 之前或之后不受 CATextLayer 的支持。您可以使用“po [[someLabel layer] class]”轻松检查它,这将产生一个基本的CALayer。这在视觉上也很明显,因为CATextLayer 没有亚像素抗锯齿但UILabel 有。 类类型并不总是具有指导意义,任何尝试过 [str isKindOfClass:[NSMutableString class]] 的人都可以证明这一点。这是一个桥接问题,显然 CALayer 并没有与任何东西正式免费桥接,但是假设 CALayer 中没有类似的类聚类或别名只是一个假设。我认为你的观点是,亚像素抗锯齿线索是相当明确的。 谢谢,很奇怪,因为这在 UIButton 上可以正常工作,但在 UILabel 上不行。我认为他们都使用相同的方式来绘制文本。 @aryaxt - 如果您查看UIButton.h 头文件,您将看到UIButton 实际上有一个名为_titleView 的实例变量。因此,对于按钮视图,这很简单,因为按钮不会绘制自己的文本,这是由子标签子视图完成的。【参考方案2】:

我遇到了同样的问题。我使用这种方法来获取形状图层的参考,或者如果它不存在则生成它。此方法确保将该图层放在后面,使其不会覆盖标签文本图层。只需使用它,你应该一切都好,不需要额外的子类。

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

【讨论】:

【参考方案3】:

例如,如果您需要将UILabel 子类化,然后添加一些覆盖文本的CALayer,建议将CATextLayer 添加到您的CALayer,这是一个快速示例:

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

【讨论】:

以上是关于Objective C - CAGradientLayer 覆盖 UILabel 中的文本?的主要内容,如果未能解决你的问题,请参考以下文章

objective-c入门

Objective-C和C的区别

objective-c与C++的区别

在 Mac OS X 上结合 Objective-C 和 C/C++

Objective-C 和 MetroWerks C/C++ IDE

objective-c和Cpp怎么混合编程?