1

I have a rectangular UIView object in a static table view cell. I have an outlet to the object and I'm trying to selectively round corners but it will not round corners on the right. Here's what it looks like in the storyboard:

enter image description here

The view I want to configure is the pale yellow one. The red view serves no real purpose other than confirming that the other view is not being clipped.

There are no constraint issues or errors. Here's how it looks on a 4S:

enter image description here

I'm doing the configuration in tableView:willDisplayCell:forRowAtIndexPath:

With this code (myView is the outlet to the pale yellow view above):

self.myView.layer.cornerRadius = 5.0f;
self.myView.clipsToBounds = YES;

I get this result:

enter image description here

All 4 corners rounded. But I need to selectively round corners, normally both top or both bottom corners. Here is the code for rounding the two bottom corners:

CAShapeLayer *shape = [[CAShapeLayer alloc] init];
shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.myView.bounds.size.width, self.myView.bounds.size.height)
                                   byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                                         cornerRadii:CGSizeMake(5.0f, 5.0f)].CGPath;
self.myView.layer.mask = shape;
self.myView.layer.masksToBounds = YES;

And here is the result:

enter image description here

It doesn't work for either of the right-hand corners. It works fine for either of the left-hand corners.

I tested the bezier code with a view object on an ordinary view controller (outside of a table view) and the code works as expected--I can round any corner selectively.

Any ideas why it's not working in a table view cell?

How can I accomplish this without resorting to drawing code?

Murray Sagal
  • 8,454
  • 4
  • 47
  • 48

4 Answers4

1

Give a try with this snippet:

CAShapeLayer *shape = [CAShapeLayer layer];
// Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.myView.bounds.bounds 
                                               byRoundingCorners:byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight
                                                     cornerRadii:CGSizeMake(5.0f, 5.0f)];

shape.frame = self.myView.bounds;
shape.path = maskPath.CGPath;

// Set the newly created shape layer as the mask for the image view's layer
self.myView.layer.mask = shape;

Layer masks will not render when used in combination with the CALayer renderInContext method. If you need to use this try rounding corners with the following: Just two rounded corners?.

Community
  • 1
  • 1
carlodurso
  • 2,886
  • 4
  • 24
  • 37
1

I think it happens because of your view's frame and therefore bounds get changed after you make a layer mask.

As documentation for tableView:willDisplayCell:forRowAtIndexPath: states: After the delegate returns, the table view sets only the alpha and frame properties, and then only when animating rows as they slide in or out.

The best tactics would be subclassing UITableViewCell and perform layer adjustments in layoutSubviews.

bteapot
  • 1,897
  • 16
  • 24
  • But as shown in the question, rounding all 4 corners works. That's a layer adjustment. – Murray Sagal Nov 18 '14 at 23:34
  • cornerRadius is a layer property that CALayer uses when drawing itself. But UIBezierPath stored in mask property won't be resized on UIVew's setBounds (when table resizes cell), so you need to change it yourself. – bteapot Nov 19 '14 at 04:34
  • Works perfectly. Bounty awarded. – Murray Sagal Nov 25 '14 at 00:29
  • I know that I'm a bit late to the fun, but my solution was to put the masking code in the tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) (im using swift) – Minebomber Apr 26 '16 at 17:10
1

Add [self.myView layoutIfNeeded];

Example:

[self.myView layoutIfNeeded];

CAShapeLayer *shape = [[CAShapeLayer alloc] init];
shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.myView.bounds.size.width, self.myView.bounds.size.height)
                                   byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                                         cornerRadii:CGSizeMake(5.0f, 5.0f)].CGPath;
self.myView.layer.mask = shape;
self.myView.layer.masksToBounds = YES;
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
0

Try adding this

shape.path = [UIBezierPath bezierPathWithRoundedRect:self.myView.bounds
                                   byRoundingCorners:UIRectCornerBottomRight
                                         cornerRadii:CGSizeMake(5.0f, 5.0f)].CGPath;

and this

shape.frame = self.myView.bounds; //Right before setting your self.mView.layer.mask = shape;
Priyatham51
  • 1,864
  • 1
  • 16
  • 24