Search code examples
iosuiviewcgpath

Resize UIView to fit a CGPath


I have a UIView subclass on which the user can add a random CGPath. The CGPath is added by processing UIPanGestures.

I would like to resize the UIView to the minimal rect possible that contains the CGPath. In my UIView subclass, I have overridden sizeThatFits to return the minimal size as such:

- (CGSize) sizeThatFits:(CGSize)size {
    CGRect box = CGPathGetBoundingBox(sigPath);
    return box.size;
}

This works as expected and the UIView is resized to the value returned, but the CGPath is also "resized" proportionally resulting in a different path that what the user had originally drawn. As an example, this is the view with a path as drawn by the user:

Path as drawn

And this is the view with the path after resizing:

enter image description here

How can I resize my UIView and not "resize" the path?


Solution

  • Use the CGPathGetBoundingBox. From Apple documentation:

    Returns the bounding box containing all points in a graphics path. The bounding box is the smallest rectangle completely enclosing all points in the path, including control points for Bézier and quadratic curves.

    Here a small proof-of-concept drawRect methods. Hope it helps you!

    - (void)drawRect:(CGRect)rect {
    
        //Get the CGContext from this view
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        //Clear context rect
        CGContextClearRect(context, rect);
    
        //Set the stroke (pen) color
        CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
    
        //Set the width of the pen mark
        CGContextSetLineWidth(context, 1.0);
    
        CGPoint startPoint = CGPointMake(50, 50);
        CGPoint arrowPoint = CGPointMake(60, 110);
    
        //Start at this point
        CGContextMoveToPoint(context, startPoint.x, startPoint.y);
        CGContextAddLineToPoint(context, startPoint.x+100, startPoint.y);
        CGContextAddLineToPoint(context, startPoint.x+100, startPoint.y+90);
        CGContextAddLineToPoint(context, startPoint.x+50, startPoint.y+90);
        CGContextAddLineToPoint(context, arrowPoint.x, arrowPoint.y);
        CGContextAddLineToPoint(context, startPoint.x+40, startPoint.y+90);
        CGContextAddLineToPoint(context, startPoint.x, startPoint.y+90);
        CGContextAddLineToPoint(context, startPoint.x, startPoint.y);
    
        //Draw it
        //CGContextStrokePath(context);
    
        CGPathRef aPathRef = CGContextCopyPath(context);
    
        // Close the path
        CGContextClosePath(context);
    
        CGRect boundingBox = CGPathGetBoundingBox(aPathRef);
        NSLog(@"your minimal enclosing rect: %.2f %.2f %.2f %.2f", boundingBox.origin.x, boundingBox.origin.y, boundingBox.size.width, boundingBox.size.height);
    }