UIView con rectángulo redondeado y la sombra: la sombra aparece encima de rectángulo

Tengo una uiview subclase donde estoy tratando de dibujar un rectángulo redondeado con sombra. Aunque hace dos elementos, puedo ver la sombra a través del rectángulo redondeado de relleno. Soy nuevo en el CG así que probablemente estoy perdiendo algo simple (aunque no parece ser el alfa de relleno que se establece en 1). Aquí está el sorteo rect código.

- (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);
}
  • Leer este post del blog bynomial.com/blog/?p=52&cpage=1#comment-1115 . Responde a cómo hacerlo.
  • la solución se documenta aquí es la mejor para mí, porque me muestra cómo utilizar una imagen personalizada (con maskToBounds =SÍ) así como de la sombra. gracias!
  • Muchas gracias por el enlace, amigo… me Ayudó a empezar. 🙂
InformationsquelleAutor Martin | 2010-02-21

3 Kommentare

  1. 17

    No creo que usted puede hacer esto en un solo paso. Hmm he cambiado el código de la siguiente manera, que parece que funciona.

    - (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);
        }
    }
    • Muy bien, gracias. Hace un montón de sentido: dibujar el rectángulo, dibuja la sombra, que es sobre el rectángulo redondeado, por lo que termine por dibujar el rectángulo de nuevo. Una nota sobre el código. Me había puesto el fondo de la vista para ver claro en mis init declaración. El código anterior funciona con cualquier otro fondo, pero con un fondo claro tuve que establecer el color de relleno antes de que el primer rectángulo es acarició y lleno de.
    • He leído que se puede extender el área de la representación de la capa para que no se recortan en el cuadro de vista. Uso: la capa.límites =CGRectMake(-1,-1,102,102) … si su vista es de 100×100 y la sombra es una de píxeles de desplazamiento, etc. Usted consigue la idea.
  2. 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];
    }
    • Muy útil, gracias!
    • La advertencia aquí es asegurarse de que su punto de vista del fondo se establece en [UIColor clearColor], de lo contrario obtendrá su sombra dibujada alrededor del marco de la vista, ignorando las esquinas redondeadas.
    • Es inútil y redundante para establecer las propiedades de la capa en drawRect:, ya que estos no cambian a menos que la cambie. Mover esas llamadas off (por ejemplo, en init…).
    • esto funciona como un encanto …gracias
  3. 15

    Probar esto 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;
    • tenga en cuenta que esto es compatible con iOS 3.2 y encima solo
    • esto no funciona con las esquinas redondeadas con maskToBounds y setCornerRadius.
    • Esta solución se ralentiza toda la aplicación notablemente …
    • Trate de añadir yourView.la capa.shouldRasterize = SÍ; para ayudar a mejorar el rendimiento.
    • ..o, establezca la capa.shadowPath como una alternativa a la shouldRasterize
    • Cómo exactamente se puede configurar el shadowPath? No estoy seguro exactamente lo que debo poner aquí..

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea