9

I can't find anything anywhere(search engines, docs, here, etc) that shows how to create rounded corners (esp. in a grouped table view) on an element that also clips the subviews.

I have code that properly creates a rounded rectangle out of a path with 4 arcs(the rounded corners) that has been tested in the drawRect: method in my subclassed uitableviewcell. The issue is that the subviews, which happen to be uibuttons with their internal uiimageviews, do no obey the CGContextClip() that the uitableviewcell obeys.

Here is the code:

- (void)drawRect:(CGRect)rect
{       
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGFloat radius = 12;
    CGFloat width = CGRectGetWidth(rect);
    CGFloat height = CGRectGetHeight(rect);

    // Make sure corner radius isn't larger than half the shorter side
    if (radius > width/2.0)
        radius = width/2.0;
    if (radius > height/2.0)
        radius = height/2.0;    

    CGFloat minx = CGRectGetMinX(rect) + 10;
    CGFloat midx = CGRectGetMidX(rect);
    CGFloat maxx = CGRectGetMaxX(rect) - 10;
    CGFloat miny = CGRectGetMinY(rect);
    CGFloat midy = CGRectGetMidY(rect);
    CGFloat maxy = CGRectGetMaxY(rect);

    [[UIColor greenColor] set];


    CGContextBeginPath(context);

    CGContextMoveToPoint(context, minx, midy);

    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);

    CGContextClip(context);
    CGContextFillRect(context, rect);

    [super drawRect:rect];    
}

Because this specific case is static(only shows in 1 specific row of buttons), I can edit the images being used for the buttons to get the desired effect.

HOWEVER, I have another case that is dynamic. Specifically, a grouped table with lots of database-driven results that will show photos that may be in the first or last row with rounded corners and thus needs to be clipped).

So, is it possible to create a CGContextClip() that also clips the subviews? If so, how?

Brenden
  • 7,708
  • 11
  • 61
  • 75
  • There is no answer here on the main question.. Is it possible to get CGContextClip() to affect subviews? – David Jeske Oct 22 '12 at 22:25
  • It's this simple ... http://stackoverflow.com/a/20410857/294884 that DOES CLIP ALL SUBVIEWS as well. – Fattie Sep 01 '14 at 14:41

5 Answers5

7

The CALayer object has functions for rounding corners:

UIView * someview = something here;
CALayer * layer = [someview layer];
layer.masksToBounds = YES;
layer.cornerRadius = radius;

And you're all set. You can also add some border colors and stuff, check out the docs in case you're interested.

Nick
  • 2,662
  • 2
  • 25
  • 48
  • 2
    You should never use CALayer's cornerRadius inside a UITableViewCell. Its performance hit is much too great for the speed that such cells must be drawn to have a fast scrolling table. – Bryan Henry Apr 27 '10 at 17:21
  • 1
    There is no way to use this for tablecells as the cornerRadius setting is for all corners. There is no way to make a rounded-top only cell – coneybeare May 11 '10 at 20:58
  • `view.layer.masksToBounds = YES` and `view.layer.cornerRadius = 8.0f` gives me exactly what I was after. Thanks. – Matt Connolly Mar 24 '11 at 05:13
  • The compiler will complain that CALayer doesn't have a cornerRadius property unless you import . And yet it recognizes the class itself. – Oscar Apr 30 '11 at 21:30
  • @Oscar -- that's because the `CALayer` reference in `UIView.h` is just a forward class reference. See line 81 (in the 6.1 SDK, anyway). – Ben Mosher Jun 26 '13 at 19:28
3

See this code: http://gist.github.com/292384

I've used it in multiple projects, the performance is great and it's highly customizable. It doesn't use cornerRadius and the drawing of the cells is context-sensitive.

james_womack
  • 10,028
  • 6
  • 55
  • 74
  • Ooh, I'm not sure that code addresses your subviews query though. Useful code for context-sensitive rounded group-style tables nonetheless. – james_womack May 02 '10 at 02:49
2

Try this in your view initialiser:

self.layer.borderWidth = 2.0f;
self.layer.borderColor = [[UIColor greenColor] CGColor];
self.layer.masksToBounds = YES;
self.layer.cornerRadius = 12.0f;

And then you don't need to implement any drawRect method at all (at least for the purposes of the round border and clipping.)

Matt Connolly
  • 9,757
  • 2
  • 65
  • 61
0

Create a subclass of UIImageView with rounded corners and transparency. The UITableViewCell itself should be opaque for better performance.

Have a look at this example.

David
  • 3,392
  • 3
  • 36
  • 47
0

If you have a custom UITableViewCell you can do this in Swift 4.0:

class CustomTVC: UITableViewCell {

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    self.layer.cornerRadius = 20
    self.layer.masksToBounds = true
}

}

richc
  • 1,648
  • 5
  • 20
  • 48