2010-07-12 137 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 2010-10-09 06:48:45

+3

您問題中的圖像鏈接中斷 – jjxtra 2012-06-19 21:36:39

回答

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的解決方案。 :) – 2010-11-29 17:00:44

+6

我創建了一些函數,以便使用這種方法更容易在GitHub上進行訪問:https://github.com/mruegenberg/objc-utils/tree/master/UIKitAdditions。請參閱InnerShadowDrawing.h/.m文件。 – mrueg 2011-03-18 11:20:01

+0

優秀的東西 – 2011-09-22 14:56:55

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

嘿山姆,這很棒,對我來說效果很好,但是你知道如何在沒有邊界的情況下獲得同樣的效果嗎?或者,也許只是一個邊界,大約是這個不透明度的一半? – 2015-11-11 19:22:50

2

是的,我有一個關於它的博客文章here。簡短的回答是從here,子類的UILabel借用JTAInnerShadowLayer,並通過覆蓋+ (Class)layerClass改變其layerclass,使其返回JTAInnerShadowLayer類是這樣的:在建立JTAInnerShadowLayer東西層init方法

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

然後像這樣:

[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您可以將它用於練習或學習,但不要一直使用它,您還應該學習如何自行創建繪圖。

聲明:我不是代言人,我只是對我的發現感到驚訝。 ;)