0

I have a custom UITableViewCell with an UIView in the background, and a UITextView on top.

The UIView is used to set the background color to white, with rounded edges to reveal the cell's contentView.backgroundColor (red) in the corners.

The UITextView height expands correctly when the user enters text.

The UIView (highlighted in the screenshot) has constraints on all 4 sides to grow together with the UITableViewCell. This works correctly (see screenshot, I also checked the frame height).

The problem is that the white UIView.backgroundColor is not expanded, so the "expanded" part is transparent, letting the red contentView.backgroundColor show.

I have tried to call setNeedsLayout on the UIView and/or the UITableViewCell in UITextViewDelegate textViewDidChange, but this did not solve the issue.

Also, setting the background colors in tableView:cellForRowAtIndexPath: or tableView:willDisplayCell:forRowAtIndexPath does not make a difference.

This seems to be similar to this SO post.

How can I have the UIView backgroundColor draw on the whole updated, expanded frame, and not just the original frame?

Screenshot

Update 2018-06-20:

Here is what I'm doing to get the rounded corners (from this SO post)

// from http://stackoverflow.com/questions/4847163/round-two-corners-in-uiview/14485362
- (void)setMaskTo:(id)sender byRoundingCorners:(UIRectCorner)corners withCornerRadii:(CGSize)radii {
    // UIButton requires this
    [sender layer].cornerRadius = 0.0;

    UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:[sender bounds]
                                                    byRoundingCorners:corners
                                                          cornerRadii:radii];

    CAShapeLayer *newCornerLayer = [CAShapeLayer layer];
    newCornerLayer.frame = [sender bounds];
    newCornerLayer.path = shapePath.CGPath;
    [sender layer].mask = newCornerLayer;
}   

Then, in tableView:cellForRowAtIndexPath: I call it with

[self setMaskTo:textInputCell.bgColorView byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) withCornerRadii:CORNER_RADII]; 
thomers
  • 2,603
  • 4
  • 29
  • 50
  • You need to change the constraints dynamically while changing the frame. – Siba Prasad Hota Jun 19 '18 at 10:33
  • Can you explain further? Currently, I don't change the frame explicitly in code. – thomers Jun 19 '18 at 10:36
  • 1
    @thomers - How are you "rounding the corners" of your white UIView? Are you setting its `layer.cornerRadius`? Or are you setting a layer path? – DonMag Jun 19 '18 at 13:13
  • @DonMag I'm setting a layer path - see my update. Am I right assuming that the problem is that I'm only setting the path once, and not updating it? If so, where/how should I update it? Or get rid of the UIBezierPath and do something else entirely? (Note that I want to define which specific corners I'm rounding) – thomers Jun 20 '18 at 08:57
  • (Revisiting the referenced SO answers about rounding specific corners, I see I could use iOS 11's CACornerMask instead of setting a bezierPathWithRoundedRect) – thomers Jun 20 '18 at 09:02
  • I can confirm that commenting out setting the layer mask fixes the problem - the UIView is growing and redrawn correctly. – thomers Jun 20 '18 at 09:07
  • @DonMag As assumed, I could fix this problem by setting layer.maskedCorners to a CACornerMask instead of creating the CAShapeLayer explicitly in code. If you want to write this as the answer, I will accept it (otherwise I will answer it myself in a few days) – thomers Jun 20 '18 at 09:33

1 Answers1

2

As mentioned in comments, if you're targeting iOS 11+ you can use CACornerMask (layer.maskedCorners) which allows you to specify specific corners to be rounded.

If you need to support iOS 10 or earlier, you can put your UIBezierPath code in layoutSubviews() - that way, you can update its frame anytime the view's frame changes.

DonMag
  • 69,424
  • 5
  • 50
  • 86