2010-05-14 19 views

Respuesta

55

No hay manera preenvasados ​​a esto, debe combinar los arcos con el fin de hacer esto, las manzanas quartzdemo proyecto muestra el código para hacer esto, aquí hay una referencia Quartz Demo y aquí está el código que proporcionan

// As a bonus, we'll combine arcs to create a round rectangle! 

// Drawing with a white stroke color 
CGContextRef context=UIGraphicsGetCurrentContext() 
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); 

// If you were making this as a routine, you would probably accept a rectangle 
// that defines its bounds, and a radius reflecting the "rounded-ness" of the rectangle. 
CGRect rrect = CGRectMake(210.0, 90.0, 60.0, 60.0); 
CGFloat radius = 10.0; 
// NOTE: At this point you may want to verify that your radius is no more than half 
// the width and height of your rectangle, as this technique degenerates for those cases. 

// In order to draw a rounded rectangle, we will take advantage of the fact that 
// CGContextAddArcToPoint will draw straight lines past the start and end of the arc 
// in order to create the path from the current position and the destination position. 

// In order to create the 4 arcs correctly, we need to know the min, mid and max positions 
// on the x and y lengths of the given rectangle. 
CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

// Next, we will go around the rectangle in the order given by the figure below. 
//  minx midx maxx 
// miny 2  3  4 
// midy 1 9    5 
// maxy 8  7  6 
// Which gives us a coincident start and end point, which is incidental to this technique, but still doesn't 
// form a closed path, so we still need to close the path to connect the ends correctly. 
// Thus we start by moving to point 1, then adding arcs through each pair of points that follows. 
// You could use a similar tecgnique to create any shape with rounded corners. 

// 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); 
+3

Si alguien se pregunta cómo 'CGContextAddArcToPoint()' obras, [esto] (http : //stackoverflow.com/a/18992153/1338292) es una buena explicación. –

11

Si desea tener esquinas redondeadas en cualquier UIView (o subclase), la manera más fácil es establecer la propiedad cornerRadius en la capa de la vista. Ver Preview rounded image in iphone

+4

Esto es de lejos el más fácil. view.layer.cornerRadius = 10.0f. Asegúrese de importar el marco de Quartz. –

123

En lugar de hacer su propio camino para salir de líneas y arcos, se puede utilizar

[UIBezierPath bezierPathWithRoundedRect:cornerRadius:] 

o

[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:] 

(el segundo le permite especificar qué esquinas redondeadas)

Disponible en iOS 3.2 o posterior.

+7

No olvide insertar correctamente el rectángulo al acariciar aunque el ancho de línea sea de solo un píxel: 'CGRectInset (rect, lineWidth, lineWidth)' – pottedmeat

+20

Solo para completar, también es útil mostrar lo que hace con eso: ' '' objc [[UIColor lightGrayColor] setFill]; // establecer el color bg de rect redondeado UIBezierPath * roundedRect = [UIBezierPath bezierPathWithRoundedRect: _yourDrawingFrame cornerRadius: 4]; [roundedRect fillWithBlendMode: kCGBlendModeNormal alpha: 1.0f]; '' ' – horseshoe7

+9

En realidad, al acariciar creo que el rect solo debe insertarse en la mitad del ancho de línea, es decir,' CGRectInset (rect, lineWidth/2.0, lineWidth/2.0) '. Esto se debe a que "la línea dibujada se centra en la ruta con sus lados paralelos al segmento de ruta" (cf. '- [UIBezierPath strokeWithBlendMode: alpha:]') – Taum

22

Aquí hay una función que escribí que redondea la entrada utilizando un radio de esquina.

CGMutablePathRef createRoundedCornerPath(CGRect rect, CGFloat cornerRadius) { 

    // create a mutable path 
    CGMutablePathRef path = CGPathCreateMutable(); 

    // get the 4 corners of the rect 
    CGPoint topLeft = CGPointMake(rect.origin.x, rect.origin.y); 
    CGPoint topRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y); 
    CGPoint bottomRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); 
    CGPoint bottomLeft = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height); 

    // move to top left 
    CGPathMoveToPoint(path, NULL, topLeft.x + cornerRadius, topLeft.y); 

    // add top line 
    CGPathAddLineToPoint(path, NULL, topRight.x - cornerRadius, topRight.y); 

    // add top right curve 
    CGPathAddQuadCurveToPoint(path, NULL, topRight.x, topRight.y, topRight.x, topRight.y + cornerRadius); 

    // add right line 
    CGPathAddLineToPoint(path, NULL, bottomRight.x, bottomRight.y - cornerRadius); 

    // add bottom right curve 
    CGPathAddQuadCurveToPoint(path, NULL, bottomRight.x, bottomRight.y, bottomRight.x - cornerRadius, bottomRight.y); 

    // add bottom line 
    CGPathAddLineToPoint(path, NULL, bottomLeft.x + cornerRadius, bottomLeft.y); 

    // add bottom left curve 
    CGPathAddQuadCurveToPoint(path, NULL, bottomLeft.x, bottomLeft.y, bottomLeft.x, bottomLeft.y - cornerRadius); 

    // add left line 
    CGPathAddLineToPoint(path, NULL, topLeft.x, topLeft.y + cornerRadius); 

    // add top left curve 
    CGPathAddQuadCurveToPoint(path, NULL, topLeft.x, topLeft.y, topLeft.x + cornerRadius, topLeft.y); 

    // return the path 
    return path; 
} 

Cómo utilizar la función, suponiendo que subclase UIView y anular drawRect:

- (void)drawRect:(CGRect)rect { 

    // constants 
    const CGFloat outlineStrokeWidth = 20.0f; 
    const CGFloat outlineCornerRadius = 15.0f; 

    const CGColorRef whiteColor = [[UIColor whiteColor] CGColor]; 
    const CGColorRef redColor = [[UIColor redColor] CGColor]; 

    // get the context 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // set the background color to white 
    CGContextSetFillColorWithColor(context, whiteColor); 
    CGContextFillRect(context, rect); 

    // inset the rect because half of the stroke applied to this path will be on the outside 
    CGRect insetRect = CGRectInset(rect, outlineStrokeWidth/2.0f, outlineStrokeWidth/2.0f); 

    // get our rounded rect as a path 
    CGMutablePathRef path = createRoundedCornerPath(insetRect, outlineCornerRadius); 

    // add the path to the context 
    CGContextAddPath(context, path); 

    // set the stroke params 
    CGContextSetStrokeColorWithColor(context, redColor); 
    CGContextSetLineWidth(context, outlineStrokeWidth); 

    // draw the path 
    CGContextDrawPath(context, kCGPathStroke); 

    // release the path 
    CGPathRelease(path); 
} 

Ejemplo de salida:

enter image description here

+0

, pero ¿por qué no utilizar las funciones integradas ?????????? – Fattie

+0

Adelante y usa las funciones incorporadas. Hice esto solo con fines de aprendizaje. –

+0

Esto no funciona: CGMutablePathRef path = createRoundedCornerPath (insetRect, outlineCornerRadius); – lespommes

41
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:bubbleBounds cornerRadius:15.0]; 
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor); 
[bezierPath stroke]; 
9

CGPathCreateWithRoundedRect() va a hacer lo que quiere.

CGPathRef CGPathCreateWithRoundedRect(
    CGRect rect, 
    CGFloat cornerWidth, 
    CGFloat cornerHeight, 
    const CGAffineTransform *transform 
); 

Disponible a partir de iOS 7.0

+3

Estoy bastante seguro de que esto NO LE DARÁ las nuevas esquinas redondeadas iOS7. Use bezierPathWithRoundedRect para las nuevas esquinas redondeadas de iOS7 ... – Fattie

+0

@JoeBlow No estoy seguro de lo que quiere decir con eso, esta función se agregó solo en iOS7 y le da esquinas redondeadas; ¿Hay otras esquinas redondeadas? –

+0

http://www.mani.de/backstage/?p=483 – Fattie

1

Tal vez ... tres? años tarde, pero en estos días estoy usando esto sin problemas.

@import CoreGraphics; 

@interface YourViewController() 
@property (weak, nonatomic) IBOutlet UIButton *theButton; 
@end 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.theButton.layer.cornerRadius = 5.0f; 
    self.theButton.layer.masksToBounds = YES; 

    // Another useful ones 
    // Scaling the view (width, height) 
    self.theButton.transform = CGAfflineTransformMakeScale(1.50f, 1.50f); 

    // Setting an alpha value (transparency) - nice with Activity Indicator subviews 
    self.theButton.alpha  = 0.8f; 
} 
4

Swift:

let rect: CGRect = ... 

    let path = UIBezierPath(roundedRect: rect, cornerRadius: 5.0) 
    CGContextAddPath(context, path.CGPath) 
    CGContextSetStrokeColorWithColor(context, UIColor.clearColor().CGColor) 
    CGContextDrawPath(context, CGPathDrawingMode.FillStroke) 
Cuestiones relacionadas