Rounded UIView using CALayers - only some corners - How?

后端 未结 14 2010
南方客
南方客 2020-11-22 13:53

In my application - there are four buttons named as follows:

  • Top - left
  • Bottom - left
  • Top - right
  • Bottom - right

Abov

14条回答
  •  囚心锁ツ
    2020-11-22 14:20

    Starting in iOS 3.2, you can use the functionality of UIBezierPaths to create an out-of-the-box rounded rect (where only corners you specify are rounded). You can then use this as the path of a CAShapeLayer, and use this as a mask for your view's layer:

    // Create the path (with only the top-left corner rounded)
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds 
                                                   byRoundingCorners:UIRectCornerTopLeft
                                                         cornerRadii:CGSizeMake(10.0, 10.0)];
    
    // Create the shape layer and set its path
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = imageView.bounds;
    maskLayer.path = maskPath.CGPath;
    
    // Set the newly created shape layer as the mask for the image view's layer
    imageView.layer.mask = maskLayer;
    

    And that's it - no messing around manually defining shapes in Core Graphics, no creating masking images in Photoshop. The layer doesn't even need invalidating. Applying the rounded corner or changing to a new corner is as simple as defining a new UIBezierPath and using its CGPath as the mask layer's path. The corners parameter of the bezierPathWithRoundedRect:byRoundingCorners:cornerRadii: method is a bitmask, and so multiple corners can be rounded by ORing them together.


    EDIT: Adding a shadow

    If you're looking to add a shadow to this, a little more work is required.

    Because "imageView.layer.mask = maskLayer" applies a mask, a shadow will not ordinarily show outside of it. The trick is to use a transparent view, and then add two sublayers (CALayers) to the view's layer: shadowLayer and roundedLayer. Both need to make use of the UIBezierPath. The image is added as the content of roundedLayer.

    // Create a transparent view
    UIView *theView = [[UIView alloc] initWithFrame:theFrame];
    [theView setBackgroundColor:[UIColor clearColor]];
    
    // Create the path (with only the top-left corner rounded)
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:theView.bounds 
                                                   byRoundingCorners:UIRectCornerTopLeft
                                                         cornerRadii:CGSizeMake(10.0f, 10.0f)];
    
    // Create the shadow layer
    CAShapeLayer *shadowLayer = [CAShapeLayer layer];
    [shadowLayer setFrame:theView.bounds];
    [shadowLayer setMasksToBounds:NO];
    [shadowLayer setShadowPath:maskPath.CGPath];
    // ...
    // Set the shadowColor, shadowOffset, shadowOpacity & shadowRadius as required
    // ...
    
    // Create the rounded layer, and mask it using the rounded mask layer
    CALayer *roundedLayer = [CALayer layer];
    [roundedLayer setFrame:theView.bounds];
    [roundedLayer setContents:(id)theImage.CGImage];
    
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    [maskLayer setFrame:theView.bounds];
    [maskLayer setPath:maskPath.CGPath];
    
    roundedLayer.mask = maskLayer;
    
    // Add these two layers as sublayers to the view
    [theView.layer addSublayer:shadowLayer];
    [theView.layer addSublayer:roundedLayer];
    

提交回复
热议问题