2

I wrote an example about Wave Animation.The animation is ok,but I don't understand why the custom UIView needs to add "self.layer.masksToBounds = YES" to have the round Corner.

  1. This is a custom UIView. I have rewritten its drawRect. If i don't set "masksToBounds" to YES, the round corner disappear.

    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            self.frame = CGRectMake(10, 40, 300, 300);
            self.layer.cornerRadius = 150;
            self.backgroundColor = [UIColor greenColor];
            self.layer.borderColor = [UIColor blueColor].CGColor;
            self.layer.borderWidth = 2;
            //        self.layer.masksToBounds = YES;  //if write this line,the round corner appear
            self.x_move = 0;
            self.y_move = 300;
        }
        return self;
    }
    
    - (void)drawRect:(CGRect)rect {
    
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGMutablePathRef path = CGPathCreateMutable();
    
        CGContextSetLineWidth(context, 1);
        CGContextSetFillColorWithColor(context, [UIColor grayColor].CGColor);
        CGPathMoveToPoint(path, NULL, 0, 0);
    
        for(float i=0; i<=300; i++){
            float x=i;
            float y = 5 * sin( 0.05 * x+ self.x_move) + self.y_move;
            CGPathAddLineToPoint(path, nil, x, y);
        }
    
        CGPathAddLineToPoint(path, nil, 300, 0);
        CGPathAddLineToPoint(path, nil, 0, 0);
        CGContextAddPath(context, path);
        CGContextFillPath(context);
        CGContextDrawPath(context, kCGPathStroke);
        CGPathRelease(path);
    }
    
    - (void)startAnimation {
        if (self.waveTimer == nil) {
            self.waveTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(refresh) userInfo:nil repeats:YES];
        }
    }
    
    - (void)refresh {
        self.x_move += 0.3;
        self.y_move -= 0.2;
        if(self.y_move - 100 < 0.00001){
            [self.waveTimer invalidate];
        }else{
            [self setNeedsDisplay];
        }
    }
    

ViewController:

self.wave = [[waveAnimation alloc] init];
[self.wave startAnimation];
[self.view addSubview:self.wave];
  1. This is a normal UIView. Its "masksToBunds" is NO, but its round corner shows normal. Compared with the examples above, why one should add, one does not need.

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 60, 100, 100)];
    view.backgroundColor = [UIColor greenColor];
    view.layer.cornerRadius = 50;
    view.layer.borderWidth = 2;
    view.layer.borderColor = [UIColor blackColor].CGColor;
    [self.view addSubview:view];
    
user4261201
  • 2,324
  • 19
  • 26

1 Answers1

0

The reason for this is from your override of drawRect:(CGRect)frame.

You are attempting to set the corner radius of the layer that is not the element you assigned the fill color to. The reason setting masksToBounds achieves the desired rounded corner is because here you are telling the view to mask all of it's layers to the bounds from your frame.

In your second example with the UIView the corner radius appears as expected because you have not adjusted it's layers.

I suggest either adopting setting masksToBounds or redraw the view's bounds a different way if you need masksToBounds = NO. Since you have the "squiggle" sin curve and you want rounded corners, perhaps just create a generic rounded rect (one with the desired corner radius) then merge that with the path you have already created with the sin wave.

Merge multiple CGPaths together to make one path

That link may help you merge your rounded view with your custom view to achieve the desired end result.

Otherwise.. probably best bet to just set this to yes.

Will Von Ullrich
  • 2,129
  • 2
  • 15
  • 42
  • 1
    Thanks for your answer!The key message is that the layer by myself drew in drawRect and self.layer are different layer.I think that creat a new layer when override "drawRect",so setting "self.layer" is not equal to set the layer drew by myself. is this right ? – Horsen Zhuge Nov 29 '17 at 02:56
  • In a round-about way I believe yes what you said is correct. Really no harm in your issue it’s merely a “behind the scenes” technicality. Try either editing the layer itself (self.layer) with your desired path or use `masksToBounds`. Hopefully my answer helped you find you solution! If u feel it did please accept – Will Von Ullrich Nov 29 '17 at 03:01
  • 1
    apple document -- cornerRadius " it applies only to the background color and border of the layer. However, setting the masksToBounds property to YES causes the content to be clipped to the rounded corners", I did not understand before,I think that overriding the "drawRect" mean that I am adjusting the content of layer. so,the cornerRadius does not work ,because the it applies only to the background color and border of the layer. – Horsen Zhuge Nov 29 '17 at 07:34
  • Correct. Like I said there is no harm using the mask property just good for you to understand *why*. Things like this are always annoying until figured out – Will Von Ullrich Nov 29 '17 at 13:55