Circular UIView (with cornerRadius) without Blended Layer

2k views Asked by At

I'm trying to get the circle below to have an opaque solid white color where the cornerRadius cuts out the UIView.

UIView *circle = [[UIView alloc] initWithFrame:CGRectMake(i * (todaySize + rightMargin), 0, smallSize, smallSize)];
circle.layer.cornerRadius = smallSize/2;
circle.layer.borderWidth = 0.5;
circle.layer.backgroundColor = [UIColor whiteColor].CGColor;
circle.backgroundColor = [UIColor whiteColor];
[self addSubview:circle];

I've tried a few things like setting the backgroundColor and opaque without any luck. Color Blended Layers still shows that the surrounding of the circle is transparent. Does anybody know how to solve this?

3

There are 3 answers

0
Sean Kladek On BEST ANSWER

To avoid blending when using rounded corners, the rounding needs to be done in drawRect, rather than as a property on the layer. I needed UICollectionView cells with a rounded background in an app I'm working on. When I used layer.cornerRadius, the performance took a huge hit. Turning on color blended layers yielded the following:

blended cells

Not what I was hoping for, I want those cells to be colored green indicating there is no blending occurring. To do this, I subclassed UIView into RoundedCornerView. My implementation is real short and sweet:

import UIKit

class RoundedCornerView: UIView {
    static let cornerRadius = 40.0 as CGFloat

    override func drawRect(rect: CGRect) {
        let borderPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: RoundedCornerView.cornerRadius)
        UIColor.whiteColor().set()
        borderPath.fill()
    }
}

Then I set the view I was rounding to be a RoundedCornerView in my nib. Running at that point yielded this:

non-blended cells

Scrolling is buttery smooth and there is no longer any blending occurring. One odd side effect of this is that the view's backgroundColor property will color the excluded area of the corners, not the main body of the view. This means that the backgroundColor should be set to whatever is behind your view, not to the desired fill color.

0
rounak On

Set clipsToBoundson the view or masksToBounds on the layer to YES

0
user3546621 On

Try using a mask to both avoid blending and dealing with the parent / child background color match.

override func layoutSubviews() {
    super.layoutSubviews()

    let maskLayer = CAShapeLayer()
    maskLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 20).cgPath
    layer.mask = maskLayer
}