UILabel的内阴影

时间:2010-07-12 19:41:51

标签: iphone objective-c uilabel

是否可以创建具有内部和外部阴影的UILabel?

alt text http://dl.getdropbox.com/u/80699/Bildschirmfoto%202010-07-12%20um%2021.28.57.png

我只知道shadowColorshadowOffset

缩放:

alt text http://dl.getdropbox.com/u/80699/Bildschirmfoto%202010-07-12%20um%2021.39.56.png

谢谢!

6 个答案:

答案 0 :(得分:126)

dmaclach的答案仅适用于易于倒置的形状。我的解决方案是一个自定义视图,适用于任何形状和文本。它需要iOS 4并且与分辨率无关。

首先,对代码的作用进行图解说明。这里的形状是一个圆圈。 alt text

代码使用白色阴影绘制文本。如果不需要,可以进一步重构代码,因为需要以不同方式屏蔽阴影。如果您需要在较旧版本的iOS上使用它,则必须替换该块并使用(恼人的)CGBitmapContext。

- (UIImage*)blackSquareOfSize:(CGSize)size {
  UIGraphicsBeginImageContextWithOptions(size, NO, 0);  
  [[UIColor blackColor] setFill];
  CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, size.width, size.height));
  UIImage *blackSquare = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return blackSquare;
}


- (CGImageRef)createMaskWithSize:(CGSize)size shape:(void (^)(void))block {
  UIGraphicsBeginImageContextWithOptions(size, NO, 0);  
  block();
  CGImageRef shape = [UIGraphicsGetImageFromCurrentImageContext() CGImage];
  UIGraphicsEndImageContext();  
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(shape),
                                      CGImageGetHeight(shape),
                                      CGImageGetBitsPerComponent(shape),
                                      CGImageGetBitsPerPixel(shape),
                                      CGImageGetBytesPerRow(shape),
                                      CGImageGetDataProvider(shape), NULL, false);
  return mask;
}


- (void)drawRect:(CGRect)rect {
  UIFont *font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:40.0f];
  CGSize fontSize = [text_ sizeWithFont:font];

  CGImageRef mask = [self createMaskWithSize:rect.size shape:^{
    [[UIColor blackColor] setFill];
    CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
    [[UIColor whiteColor] setFill];
    // custom shape goes here
    [text_ drawAtPoint:CGPointMake((self.bounds.size.width/2)-(fontSize.width/2), 0) withFont:font];
    [text_ drawAtPoint:CGPointMake((self.bounds.size.width/2)-(fontSize.width/2), -1) withFont:font];
  }];

  CGImageRef cutoutRef = CGImageCreateWithMask([self blackSquareOfSize:rect.size].CGImage, mask);
  CGImageRelease(mask);
  UIImage *cutout = [UIImage imageWithCGImage:cutoutRef scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUp];
  CGImageRelease(cutoutRef);  

  CGImageRef shadedMask = [self createMaskWithSize:rect.size shape:^{
    [[UIColor whiteColor] setFill];
    CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
    CGContextSetShadowWithColor(UIGraphicsGetCurrentContext(), CGSizeMake(0, 1), 1.0f, [[UIColor colorWithWhite:0.0 alpha:0.5] CGColor]);
    [cutout drawAtPoint:CGPointZero];
  }];

  // create negative image
  UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
  [[UIColor blackColor] setFill];
  // custom shape goes here
  [text_ drawAtPoint:CGPointMake((self.bounds.size.width/2)-(fontSize.width/2), -1) withFont:font];
  UIImage *negative = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext(); 

  CGImageRef innerShadowRef = CGImageCreateWithMask(negative.CGImage, shadedMask);
  CGImageRelease(shadedMask);
  UIImage *innerShadow = [UIImage imageWithCGImage:innerShadowRef scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUp];
  CGImageRelease(innerShadowRef);

  // draw actual image
  [[UIColor whiteColor] setFill];
  [text_ drawAtPoint:CGPointMake((self.bounds.size.width/2)-(fontSize.width/2), -0.5) withFont:font];
  [[UIColor colorWithWhite:0.76 alpha:1.0] setFill];
  [text_ drawAtPoint:CGPointMake((self.bounds.size.width/2)-(fontSize.width/2), -1) withFont:font];  

  // finally apply shadow
  [innerShadow drawAtPoint:CGPointZero];
}

答案 1 :(得分:13)

尽管史蒂夫的回答确实有效,但它并没有扩展到我的特定情况,因此我在剪辑上下文后通过将阴影应用于CGPath来创建内部阴影:

CGContextRef context = UIGraphicsGetCurrentContext();

// clip context so shadow only shows on the inside
CGPathRef roundedRect = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4].CGPath;
CGContextAddPath(context, roundedRect);
CGContextClip(context);

CGContextAddPath(context, roundedRect);
CGContextSetShadowWithColor(UIGraphicsGetCurrentContext(), CGSizeMake(0, 0), 3, [UIColor colorWithWhite:0 alpha:1].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:0 alpha:1].CGColor);
CGContextStrokePath(context);

结果是:

enter image description here

您可以更改阴影偏移和模糊以更改阴影样式。如果你需要它更暗,你也可以连续添加然后抚摸相同的CGPath,这将使阴影堆积起来。

答案 2 :(得分:7)

我使用FXLabel作为内部阴影,请看https://github.com/nicklockwood/FXLabel

答案 3 :(得分:2)

是的,我有一篇关于它的博客文章here。简短的回答是从here子类UILabel借用JTAInnerShadowLayer,并通过覆盖+ (Class)layerClass来更改其图层类,以便它返回JTAInnerShadowLayer类,如下所示:

+ (Class)layerClass
{
  return [JTAInnerShadowLayer class];
}

然后在图层的init方法中设置JTAInnerShadowLayer,如下所示:

[self setBackgroundColor:[UIColor clearColor]];
JTAInnerShadowLayer *innerShadow = (JTAInnerShadowLayer *)[self layer];
[innerShadow setClipForAnyAlpha:YES];
[innerShadow setOutsideShadowSize:CGSizeMake(0.0, 1.0) radius:1.0];
[innerShadow setInsideShadowSize:CGSizeMake (0.0, 4.0) radius:6.0];
/* Uncomment this to make the label also draw the text (won't work well
   with black text!*/
//[innerShadow drawOriginalImage];

(或者只是借用JTAIndentLabel类)。

答案 4 :(得分:0)

您必须自己制作自定义绘图才能获得内在阴影。目前没有办法使用标准的UILabel。

以下是使用Quartz进行内部阴影的合理解释。

Inner shadow in Core Graphics

答案 5 :(得分:0)

试用PaintCode试用版!对于初学者,您将学习如何创建自定义绘图。这是很不错的! :3您可以将它用于练习或学习,但不要一直使用它,您还应该学习如何自己创建绘图。

免责声明:我不是代言人,我对我的发现感到惊讶。 ;)