2010-07-12 28 views
17

là nó có thể tạo ra một UILabel với bóng bên trong và bên ngoài?Inner Shadow trong UILabel

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

tôi chỉ biết shadowColorshadowOffset

thu nhỏ:

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

cảm ơn!

+0

Tôi cũng muốn biết điều này để mô phỏng một UITextField cách đây khá lâu và đã sử dụng Quartz (như gợi ý) nhưng có một số vấn đề về hiệu suất, tôi khá chắc chắn rằng hoạt hình giới hạn của UILabel rendering bóng theo cách đó sẽ không đẹp. Nó sẽ trông chậm chạp. Trong trường hợp của tôi tôi đã kết thúc bằng cách sử dụng một UIImage kéo dài: stretchableImageWithLeftCapWidth: topCapHeight: nó nhanh hơn nhiều nếu nó phù hợp với nhu cầu của bạn – nacho4d

+3

Liên kết hình ảnh trong câu hỏi của bạn bị hỏng – jjxtra

Trả lời

125

Câu trả lời bởi dmaclach chỉ thích hợp cho hình dạng mà có thể dễ dàng được đảo ngược. Giải pháp của tôi là chế độ xem tùy chỉnh hoạt động với mọi hình dạng và văn bản. Nó đòi hỏi iOS 4 và có độ phân giải độc lập.

Đầu tiên, giải thích bằng hình ảnh về mã của mã. Hình dạng ở đây là hình tròn. alt text

Mã vẽ văn bản có màu trắng. Nếu nó không được yêu cầu, mã có thể được tái cấu trúc thêm, bởi vì dropshadow cần phải được che dấu khác nhau. Nếu bạn cần nó trên một phiên bản cũ của iOS, bạn sẽ phải thay thế khối và sử dụng một (gây phiền nhiễu) 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

Ồ, điều đó thực sự hữu ích! Không biết tại sao không có phiếu bầu ... Thật không may, không thể đặt nhiều hơn 1 cho giải pháp. :) –

+6

Tôi đã tạo một số chức năng để sử dụng phương pháp này dễ dàng hơn trên GitHub: https://github.com/mruegenberg/objc-utils/tree/master/UIKitAdditions. Xem các tệp InnerShadowDrawing.h/.m. – mrueg

+0

công cụ tuyệt vời –

0

Bạn sẽ phải thực hiện bản vẽ tùy chỉnh của riêng mình để có được bóng bên trong. Hiện tại không có cách nào để làm điều đó với một UILabel chuẩn.

Dưới đây là giải thích hợp lý về làm bóng bên trong với Thạch anh.

Inner shadow in Core Graphics

13

Mặc dù câu trả lời của Steve làm việc, nó đã không mở rộng cho trường hợp cụ thể của tôi và vì vậy tôi đã kết thúc việc tạo ra một inner shadow bằng cách áp dụng một bóng tối để một CGPath sau khi cắt bối cảnh của tôi:

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

mà kết quả trong:

enter image description here

Bạn có thể thay đổi cái bóng bù đắp và làm mờ để thay đổi phong cách bóng. Nếu bạn cần nó tối hơn, bạn cũng có thể tiếp tục thêm và sau đó đột quỵ cùng một CGPath, mà sẽ làm cho bóng đổ lên.

+0

Xin chào Sam, điều này thật tuyệt vời và hoạt động tốt cho tôi, nhưng bạn có biết làm thế nào để có được hiệu ứng tương tự mà không có biên giới? Hoặc có lẽ chỉ là một đường viền khoảng một nửa độ mờ đục như cái này? –

2

Có, tôi có một bài đăng trên blog về nó here. Câu trả lời ngắn gọn là để mượn JTAInnerShadowLayer từ here, lớp con UILabel, và thay đổi layerclass của nó bằng cách ghi đè + (Class)layerClass để nó trả về JTAInnerShadowLayer lớp như thế này:

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

Sau đó, trong phương pháp init cho lớp thiết lập một cái gì đó JTAInnerShadowLayer như thế này:

[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]; 

(hoặc chỉ mượn lớp JTAIndentLabel).

0

Hãy thử PaintCode phiên bản dùng thử!Đối với người mới bắt đầu, bạn sẽ tìm hiểu cách tạo bản vẽ tùy chỉnh. Nó rất đẹp! : 3 Bạn có thể sử dụng nó để thực hành hoặc học tập, nhưng không sử dụng nó mọi lúc, bạn cũng nên học cách tự tạo bản vẽ.

Tuyên bố từ chối trách nhiệm: Tôi không phải là người ủng hộ, tôi đã rất ngạc nhiên trước khám phá của mình. ;)