2011-01-30 29 views
18

En mi aplicación para iPad, quiero que aparezca una segunda vista en la página principal cuando el usuario haga clic en un botón. La nueva vista será más pequeña que la primera y oscurecerá el fondo cuando se muestre. Quiero que las dos esquinas superiores de la nueva vista aparezcan redondeadas, pero al usar cornerRadius las redondea todas. ¿Cómo puedo hacer solo dos esquinas redondeadas?¿Solo dos esquinas redondeadas?

Respuesta

17

Tienes que hacer esto en drawRect :. En realidad he modificado el addRoundedRectToPath clásica: por lo que se necesita un mapa de bits y redondea las esquinas se solicitan:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, UIImageRoundedCorner cornerMask) 
{ 
    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius); 
    CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius); 
    if (cornerMask & UIImageRoundedCornerTopLeft) { 
     CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, 
         radius, M_PI, M_PI/2, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height); 
     CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y + rect.size.height); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, 
          rect.origin.y + rect.size.height); 

    if (cornerMask & UIImageRoundedCornerTopRight) { 
     CGContextAddArc(context, rect.origin.x + rect.size.width - radius, 
         rect.origin.y + rect.size.height - radius, radius, M_PI/2, 0.0f, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - radius); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius); 

    if (cornerMask & UIImageRoundedCornerBottomRight) { 
     CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius, 
         radius, 0.0f, -M_PI/2, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y); 
     CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius, rect.origin.y); 
    } 

    CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y); 

    if (cornerMask & UIImageRoundedCornerBottomLeft) { 
     CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius, 
         -M_PI/2, M_PI, 1); 
    } 
    else { 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y); 
     CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + radius); 
    } 

    CGContextClosePath(context); 
} 

esto lleva una máscara de bits (lo llamé UIImageRoundedCorner porque yo estaba haciendo esto para imágenes, pero se puede llamar lo) y luego construye un camino basado en las esquinas que desea redondear. A continuación, aplicar ese camino a la vista en drawRect:

CGContextBeginPath(context); 
addRoundedRectToPath(context, rect, radius, yourMask); 
CGContextClosePath(context); 
CGContextClip(context); 

Como ya he dicho, yo estaba haciendo esto para UIImages, por lo que mi código no se ajusta exactamente para su uso en drawRect :, pero debe ser bastante fácil para adaptarlo. Básicamente, estás construyendo un camino y luego recortándole el contexto.

Editar: para explicar la parte de máscara de bits, es sólo una enumeración:

typedef enum { 
    UIImageRoundedCornerTopLeft = 1, 
    UIImageRoundedCornerTopRight = 1 << 1, 
    UIImageRoundedCornerBottomRight = 1 << 2, 
    UIImageRoundedCornerBottomLeft = 1 << 3 
} UIImageRoundedCorner; 

De esta manera se puede o cosas juntos para formar una máscara de bits que identifica las esquinas, ya que cada miembro de la enumeración representa una diferente potencia de dos en la máscara de bits.

Mucho más tarde Editar: he descubierto una manera más fácil de hacer esto utilizando UIBezierPath 's bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:. Simplemente use el objeto de ruta Bezier CGPath en su contexto.

+0

Gran respuesta! Solo necesito ayuda para implementarlo. En primer lugar, ¿cómo puedo hacer mi propia máscara de bits? – Jumhyn

+0

Editando la respuesta para explicar enum. – kevboh

+0

Mi respuesta está hecha para tomar las curvas que quieras redondear. Si solo necesita las dos esquinas superiores y no le importan las demás, podría editar las tonterías de la máscara de bits y simplemente usar las dos secciones que corresponden a las esquinas que necesita redondear. – kevboh

56
// Create the path (with only the top-left corner rounded) 
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
          byRoundingCorners:UIRectCornerTopLeft| UIRectCornerTopRight 
          cornerRadii:CGSizeMake(10.0, 10.0)]; 
// Create the shape layer and set its path 
CAShapeLayer *maskLayer = [CAShapeLayer layer]; 
maskLayer.frame = imageView.bounds; 
maskLayer.path = maskPath.CGPath; 
// Set the newly created shape layer as the mask for the image view's layer 
imageView.layer.mask = maskLayer; 

Esta es otra esquina superior redondeada. Round two corners in UIView

+2

Eso funciona bien ..gracias mucho –

+0

Eso funciona, PERO causa la representación fuera de pantalla en toda el área 'imageView', lo que resulta en animación tartamuda – Philip007

+0

¡La mejor respuesta que he encontrado sobre el tema! – PaperThick

8

El maravilloso trabajo realizado por Tomek Kuźma. Aquí está la nueva clase TKRoundedView para su requerimiento.
Su requisito puede cumplirse solo con este parámetro.

TKRoundedView *view = [[TKRoundedView alloc] initWithFrame:frame]; 
view.roundedCorners = TKRoundedCornerTopLeft | TKRoundedCornerTopRight; 

Pero también ofrece las siguientes características adicionales.

TKRoundedView *view = [[TKRoundedView alloc] initWithFrame:frame]; 
view.roundedCorners = TKRoundedCornerTopLeft 
view.borderColor = [UIColor greenColor]; 
view.fillColor = [UIColor whiteColor]; 
view.drawnBordersSides = TKDrawnBorderSidesLeft | TKDrawnBorderSidesTop; 
view.borderWidth = 5.0f; 
view.cornerRadius = 15.0f; 

favor de partida de los siguiente enlace para el proyecto de ejemplo
https://github.com/mapedd/TKRoundedView

+0

^¡muy bien! Funciona muy bien con el diseño automático. –