2010-07-12 6 views
17

내부 및 외부 그림자가있는 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

감사합니다!

+0

나는 꽤 오래 전에 UITextField를 시뮬레이트하기 위해이 사실을 알고 싶었고 Quartz (권장)를 사용했지만 성능상의 문제가있다. UILabel 렌더링 그림자의 경계에 애니메이션을 적용하는 것이 좋습니다. 좋아 보이지 않을거야. 그것은 부진 해 보일 것이다. 내 경우에는 뻗어 UIImage를 사용하여 끝났다 : stretchableImageWithLeftCapWidth : topCapHeight : 그것은 귀하의 요구에 맞는 경우 훨씬 빠릅니다. – nacho4d

+3

질문에 이미지 링크가 깨졌습니다. – jjxtra

답변

125

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]; 
} 
+0

와우, 정말 도움이되었습니다! 왜 제로 표가 있었는지 모르겠군요 ... 불행히도 해결책에 +1 이상을 설정할 수는 없습니다. :) –

+6

GitHub : https://github.com/mruegenberg/objc-utils/tree/master/UIKitAdditions에서이 방법을 사용하는 것이 더 쉽도록 몇 가지 기능을 만들었습니다. InnerShadowDrawing.h/.m 파일을 참조하십시오. – mrueg

+0

우수한 물건 –

0

내면의 그림자를 얻으려면 사용자 지정 그리기를 수행해야합니다. 현재 표준 UILabel로 수행 할 방법이 없습니다.

Quartz로 내부 그림자를 만드는 것에 대한 합리적인 설명이 있습니다.

Inner shadow in Core Graphics

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를 추가 한 다음 획을 그어 그림자를 쌓아 올릴 수 있습니다.

+0

안녕하세요 샘, 위대하고 잘 작동하지만 경계없이이 같은 효과를 얻는 방법을 알고 있습니까? 아니면이 경계선의 절반 정도의 불투명도일까요? –

7

내 그림자에 FXLabel을 사용합니다. 여기서는 https://github.com/nicklockwood/FXLabel을 참조하십시오.

+3

놀라운 놀랍군! 그것은 스테로이드에 UILabel 같이이다! 감사! –

2

예, 블로그 게시물이 here입니다. JTAInnerShadowLayer 뭔가를 설정 레이어의 초기화 방법에 그런

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

: 짧은 대답은이 같은 JTAInnerShadowLayer 클래스를 반환하도록 here, 서브 클래스 UILabel의에서 JTAInnerShadowLayer을 빌려 및 + (Class)layerClass를 오버라이드 (override)의 layerclass을 변경하는 것입니다 다음과 같이하십시오 :

[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

시도 PaintCode 평가판!초보자를 위해 맞춤형 그림을 만드는 방법을 배웁니다. 아주 좋다! : 3 연습이나 학습을 위해 사용할 수 있지만 항상 사용하지는 말고 직접 그림을 만드는 방법을 배워야합니다.

면책 조항 : 저는 보증인이 아니며, 발견 한 것에 놀랐습니다. ;)