2010-02-21 46 views
24

Tôi đã có một lớp con uiview nơi tôi đang cố gắng để vẽ một hình chữ nhật tròn với một bóng đổ. Mặc dù nó vẽ cả hai yếu tố, tôi có thể nhìn thấy bóng qua hình chữ nhật được làm tròn. Tôi mới đến CG vì vậy tôi có thể thiếu một cái gì đó đơn giản (mặc dù nó không có vẻ là alpha của điền được thiết lập để 1). Đây là mã vẽ trực tiếp.UIView với hình chữ nhật tròn và bóng đổ: bóng xuất hiện phía trên hình chữ nhật

- (void)drawRect:(CGRect)rect { 
    // get the contect 
CGContextRef context = UIGraphicsGetCurrentContext(); 

//for the shadow, save the state then draw the shadow 
CGContextSaveGState(context); 
    CGContextSetShadow(context, CGSizeMake(4,-5), 10); 



//now draw the rounded rectangle 
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0); 

//since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame 
CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30); 
CGFloat radius = self.cornerRadius; 
// the rest is pretty much copied from Apples example 
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

// Start at 1 
CGContextMoveToPoint(context, minx, midy); 
// Add an arc through 2 to 3 
CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
// Add an arc through 4 to 5 
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
// Add an arc through 6 to 7 
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
// Add an arc through 8 to 9 
CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
// Close the path 
CGContextClosePath(context); 
// Fill & stroke the path 
CGContextDrawPath(context, kCGPathFillStroke); 

//for the shadow 
    CGContextRestoreGState(context); 
} 
+1

đã đọc bài viết trên blog này http://bynomial.com/blog/?p=52&cpage=1#comment-1115. Nó trả lời làm thế nào để làm điều này. –

+0

các giải pháp tài liệu ở đây là tốt nhất cho tôi, bởi vì nó cho tôi thấy làm thế nào để sử dụng một hình ảnh tùy chỉnh (với maskToBounds = YES) cũng như bóng tối. cảm ơn! – Mark

+0

@ John: Rất nhiều người cảm ơn vì liên kết, bạn thân ... đã giúp tôi bắt đầu. :) – viral

Trả lời

16

Tôi không nghĩ rằng bạn có thể làm điều này trong một lần. Hmm Tôi đã thay đổi mã của bạn như sau, mà dường như làm việc.

- (void)drawRect:(CGRect)rect 
{ 
    // get the contect 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    //now draw the rounded rectangle 
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 0.0); 

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame 
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30); 
    CGFloat radius = 45; 
    // the rest is pretty much copied from Apples example 
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

    { 
     //for the shadow, save the state then draw the shadow 
     CGContextSaveGState(context); 

     // Start at 1 
     CGContextMoveToPoint(context, minx, midy); 
     // Add an arc through 2 to 3 
     CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
     // Add an arc through 4 to 5 
     CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
     // Add an arc through 6 to 7 
     CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
     // Add an arc through 8 to 9 
     CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
     // Close the path 
     CGContextClosePath(context); 

     CGContextSetShadow(context, CGSizeMake(4,-5), 10); 
     CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 

     // Fill & stroke the path 
     CGContextDrawPath(context, kCGPathFillStroke); 

     //for the shadow 
     CGContextRestoreGState(context); 
    } 

    { 
     // Start at 1 
     CGContextMoveToPoint(context, minx, midy); 
     // Add an arc through 2 to 3 
     CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
     // Add an arc through 4 to 5 
     CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
     // Add an arc through 6 to 7 
     CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
     // Add an arc through 8 to 9 
     CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
     // Close the path 
     CGContextClosePath(context); 

     CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]); 
     CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);  

     // Fill & stroke the path 
     CGContextDrawPath(context, kCGPathFillStroke); 
    } 
} 
+0

Tuyệt vời, cảm ơn. Làm cho rất nhiều ý nghĩa: bạn vẽ hình chữ nhật, vẽ bóng, mà là ở trên hình chữ nhật tròn, vì vậy bạn kết thúc bằng cách vẽ hình chữ nhật một lần nữa. Một lưu ý trên mã của bạn. Tôi đã thiết lập nền của khung nhìn để xóa trong câu lệnh init của tôi. Đoạn mã trên hoạt động với bất kỳ nền nào khác, nhưng với một nền rõ ràng, tôi đã phải thiết lập màu tô trước khi hình chữ nhật đầu tiên được vuốt và lấp đầy. – Martin

+0

Tôi đọc rằng bạn có thể mở rộng diện tích của lớp được hiển thị để nó không bị cắt bớt bởi khung nhìn. Sử dụng: layer.bounds = CGRectMake (-1, -1,102,102) ... nếu chế độ xem của bạn là 100x100 và bóng đổ là điểm ảnh bù đắp, v.v. Bạn sẽ có ý tưởng. –

15

Hãy thử điều này sau khi bạn nhập QuartzCore/QuartzCore.h

yourView.layer.shadowColor = [[UIColor blackColor] CGColor]; 
yourView.layer.shadowOffset = CGSizeMake(10.0f, 10.0f); 
yourView.layer.shadowOpacity = 1.0f; 
yourView.layer.shadowRadius = 10.0f; 
+1

lưu ý rằng điều này được hỗ trợ bởi iOS 3.2 trở lên chỉ –

+1

điều này không hoạt động với các góc được làm tròn bằng cách sử dụng _maskToBounds và setCornerRadius_. –

+2

Giải pháp này làm chậm toàn bộ ứng dụng đáng chú ý ... – Ondrej

39
- (void)drawRect:(CGRect)rect 
{ 
    self.layer.masksToBounds = NO; 
    self.layer.shadowColor = [[UIColor whiteColor] CGColor]; 
    self.layer.shadowOffset = CGSizeMake(0,2); 
    self.layer.shadowRadius = 2; 
    self.layer.shadowOpacity = 0.2; 

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(20, 20)]; 
    [[UIColor blackColor] setFill]; 

    [path fill]; 
} 
+0

Rất hữu ích, cảm ơn! – Gabriel

+0

Thông báo trước ở đây là để đảm bảo rằng nền của chế độ xem của bạn được đặt thành [UIColor clearColor], nếu không bạn sẽ nhận được bóng của bạn được vẽ xung quanh khung của chế độ xem, bỏ qua các góc được làm tròn. – Julian

+2

Nó là không cần thiết và dư thừa để thiết lập các thuộc tính lớp trong drawRect :, vì chúng không thay đổi trừ khi bạn thay đổi chúng. Di chuyển các cuộc gọi đó (ví dụ: trong init ...). – millenomi

Các vấn đề liên quan