2010-02-21 21 views
24

Tengo una subclase uiview en la que intento dibujar un rectángulo redondeado con una sombra paralela. Aunque dibuja ambos elementos, puedo ver la sombra a través del relleno de rectángulo redondeado. Soy nuevo en CG, así que probablemente me esté perdiendo algo simple (aunque no parece ser el alfa del relleno que está configurado en 1). Aquí está el código dibujar rect.UIView con rectángulo redondeado y sombra paralela: la sombra aparece sobre el rectángulo

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

Leer esta entrada del blog http://bynomial.com/blog/?p=52&cpage=1#comment-1115. Responde cómo hacer esto. –

+0

la solución documentada aquí es la mejor para mí, porque me muestra cómo usar una imagen personalizada (con maskToBounds = YES) además de la sombra. ¡Gracias! – Mark

+0

@John: Muchas muchas gracias por el enlace, amigo ... Me ayudó a comenzar. :) – viral

Respuesta

16

No creo que pueda hacer esto en una sola pasada. Hmm, cambié tu código de la siguiente manera, lo que parece funcionar.

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

Genial, gracias. Tiene mucho sentido: dibujar el rectángulo, dibujar la sombra, que está por encima del rectángulo redondeado, por lo que termina dibujando el rectángulo de nuevo. Una nota en su código. Establecí el fondo de la vista para borrar en mi declaración de inicio. El código anterior funciona con cualquier otro fondo, pero con un fondo claro tuve que establecer el color de relleno antes de que se toque y rellene el primer rectángulo. – Martin

+0

Leí que puede extender el área de la capa procesada para que no quede recortada por el marco de la vista. Use: layer.bounds = CGRectMake (-1, -1,102,102) ... si su vista es 100x100 y la sombra es un desplazamiento de píxeles, etc. Se entiende la idea. –

15

probar este después de importar 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

tenga en cuenta que esto es compatible con iOS 3.2 y superior solo –

+1

esto no funciona con las esquinas redondeadas usando _maskToBounds y setCornerRadius_. –

+2

Esta solución ralentiza notablemente toda la aplicación ... – 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

¡Muy útil, gracias! – Gabriel

+0

La única advertencia es asegurarse de que el fondo de su vista esté configurado en [UIColor clearColor]; de lo contrario, se dibujará su sombra alrededor del marco de la vista, ignorando las esquinas redondeadas. – Julian

+2

No es útil y redundante establecer propiedades de capa en drawRect :, ya que estas no cambian a menos que las modifique. Quita esas llamadas (por ejemplo, en init ...). – millenomi

Cuestiones relacionadas