2010-02-21 2 views
24

У меня есть подкласс uiview, где я пытаюсь нарисовать округленный прямоугольник с тенью. Хотя он рисует оба элемента, я вижу тень через закругленный прямоугольник. Я новичок в CG, поэтому я, вероятно, пропустил что-то простое (хотя, похоже, это не альфа заполнения, которая установлена ​​в 1). Вот обратный код.UIView с закругленным прямоугольником и теневой тень: тень появляется над прямоугольником

- (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

Читать этот блог http://bynomial.com/blog/?p=52&cpage=1#comment-1115. Он отвечает, как это сделать. –

+0

решение, задокументированное здесь, является лучшим для меня, потому что оно показывает мне, как использовать пользовательский образ (с maskToBounds = YES), а также тень. благодаря! – Mark

+0

@John: Большое спасибо за ссылку, приятель ... Помогло мне начать. :) – viral

ответ

16

Я не думаю, что вы можете сделать это за один проход. Хм, я изменил ваш код следующим образом, который, похоже, работает.

- (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

Отлично, спасибо. Делает большой смысл: вы рисуете прямоугольник, рисуете тень, которая находится над закругленным прямоугольником, поэтому вы закончите, снова рисуя прямоугольник. Одно примечание к вашему коду. Я установил фон представления, чтобы очистить его в инструкции init. Вышеприведенный код работает с любым другим фоном, но с ясным фоном мне пришлось установить цвет заливки до того, как первый прямоугольник будет поглажен и заполнен. – Martin

+0

Я читал, что вы можете расширить область отображаемого слоя, чтобы он не был обрезан рамкой вида. Используйте: layer.bounds = CGRectMake (-1, -1,102,102) ... если ваше представление 100x100, а тень - смещение пикселей и т. Д. Вы получаете идею. –

15

Попробуйте это после того, как вы импортируете 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

Обратите внимание, что это поддерживается iOS 3.2 и выше только –

+1

, это не работает с закругленными углами, используя _maskToBounds и setCornerRadius_. –

+2

Это решение заметно замедляет работу приложения ... – 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

Очень полезно, спасибо! – Gabriel

+0

Здесь необходимо указать, что фон вашего представления установлен на [UIColor clearColor], иначе вы получите тень, нарисованную вокруг рамки представления, игнорируя закругленные углы. – Julian

+2

Недопустимо и избыточно устанавливать свойства слоя в drawRect :, поскольку они не меняются, если вы их не измените. Отключите эти вызовы (например, в init ...). – millenomi

Смежные вопросы