Внутренняя тень в UILabel - PullRequest
18 голосов
/ 12 июля 2010

возможно ли создать такой UILabel с внутренней и внешней тенью?

альтернативный текст http://dl.getdropbox.com/u/80699/Bildschirmfoto%202010-07-12%20um%2021.28.57.png

я знаю только shadowColor и shadowOffset

увеличена:

альтернативный текст http://dl.getdropbox.com/u/80699/Bildschirmfoto%202010-07-12%20um%2021.39.56.png

спасибо!

Ответы [ 6 ]

126 голосов
/ 08 октября 2010

Ответ 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];
}
13 голосов
/ 12 января 2012

Хотя ответ Стива работает, он не масштабировался в моем конкретном случае, и поэтому я закончил тем, что создал внутреннюю тень, применив тень к 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, что приведет к накапливанию теней.

7 голосов
/ 18 марта 2013

Я использую FXLabel для внутренней тени, смотрите здесь https://github.com/nicklockwood/FXLabel.

2 голосов
/ 19 июля 2013

Да, у меня есть запись в блоге об этом здесь . Краткий ответ - заимствовать JTAInnerShadowLayer из здесь , подкласса UILabel, и изменить его уровень слоя, переопределив + (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).

0 голосов
/ 27 января 2014

Попробуйте PaintCode пробная версия! Для начинающих вы узнаете, как создавать собственные рисунки. Это очень приятно! : 3 Вы можете использовать это для практики или для обучения, но не используйте это все время, вы должны также научиться создавать рисунки самостоятельно.

Отказ от ответственности: я не индоссант, я был просто поражен своим открытием. ;)

0 голосов
/ 13 июля 2010

Вы должны будете сделать свой собственный рисунок, чтобы получить внутреннюю тень.В настоящее время нет способа сделать это с помощью стандартной UILabel.

Вот разумное объяснение создания внутренней тени с помощью Quartz.

Внутренняя тень в Core Graphics

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...