skip to Main Content

I apply cornerRadius for UIView, and apply the border color.
But, I can see the wrong color at the corner.
This image below is an enlarged image for simulator.

simulator

And this image below is debug view hierarchy.

enter image description here

How is fix that?

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .black
        
        let test = UIView()
        test.backgroundColor = .white
        test.layer.cornerRadius = 7
        test.layer.borderColor = UIColor.black.cgColor
        test.layer.borderWidth = 2
        
        view.addSubview(test)
        
        test.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            test.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
            test.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
            test.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
            test.heightAnchor.constraint(equalToConstant: 40)
        ])
    }
}

2

Answers


  1. I hope I’m correct with your remark, that the border color is not right, because you still see the edges of the background color white on the outer edges of your view.

    If that’s the case, you can easily get rid of that with setting your view to clipsToBounds is true. your code then looks only slightly different.

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = .black
            
            let test = UIView()
            test.backgroundColor = .white
            test.clipsToBounds = true
            test.layer.cornerRadius = 7
            test.layer.borderColor = UIColor.black.cgColor
            test.layer.borderWidth = 2
            
            view.addSubview(test)
            
            test.translatesAutoresizingMaskIntoConstraints = false
            
            NSLayoutConstraint.activate([
                test.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
                test.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
                test.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15),
                test.heightAnchor.constraint(equalToConstant: 40)
            ])
        }
    }
    

    This should solve your problem with the edges.

    Login or Signup to reply.
  2. OK – what you’re seeing is "artifacts" of anti-aliasing of the border… because the border is draw on the inside of the view.

    It’s been this way since (I believe) the first version of iOS.

    The artifacts are even more noticeable when using a corner radius to make the view round:

    enter image description here

    and zoomed-in to 200%:

    enter image description here

    The way to avoid this is to use a CAShapeLayer with a rounded-corner UIBezierPath.

    Here’s a quick example view subclass, with public properties similar to what you’re already using on the .layer:

    class ExampleView: UIView {
        public var fillColor: CGColor = UIColor.clear.cgColor {
            didSet {
                shapeLayer.fillColor = fillColor
            }
        }
        public var strokeColor: CGColor = UIColor.clear.cgColor {
            didSet {
                shapeLayer.strokeColor = strokeColor
            }
        }
        public var lineWidth: CGFloat = 0 {
            didSet {
                shapeLayer.lineWidth = lineWidth
            }
        }
        public var cornerRadius: CGFloat = 0 {
            didSet {
                shapeLayer.cornerRadius = cornerRadius
            }
        }
        private var shapeLayer: CAShapeLayer!
        override class var layerClass: AnyClass {
            return CAShapeLayer.self
        }
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        private func commonInit() -> Void {
            shapeLayer = self.layer as? CAShapeLayer
            shapeLayer.fillColor = fillColor
            shapeLayer.strokeColor = strokeColor
            shapeLayer.lineWidth = lineWidth
        }
        override func layoutSubviews() {
            super.layoutSubviews()
            let pth = UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius)
            shapeLayer.path = pth.cgPath
        }
    
    }
    

    That gives us:

    enter image description here

    and, again zoomed-in to 200%:

    enter image description here

    Here’s an example view controller showing the differences:

    class ExampleViewController: UIViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.backgroundColor = .black
            
            let test = UIView()
            test.backgroundColor = .white
            test.layer.cornerRadius = 7
            test.layer.borderColor = UIColor.black.cgColor
            test.layer.borderWidth = 2
            
            
            let circleTest = UIView()
            circleTest.backgroundColor = .white
            circleTest.layer.cornerRadius = 20
            circleTest.layer.borderColor = UIColor.black.cgColor
            circleTest.layer.borderWidth = 2
    
            
            let myTest = ExampleView()
            myTest.backgroundColor = .white
            myTest.cornerRadius = 7
            myTest.strokeColor = UIColor.black.cgColor
            myTest.lineWidth = 2
            
    
            let myCircleTest = ExampleView()
            myCircleTest.backgroundColor = .white
            myCircleTest.cornerRadius = 20
            myCircleTest.strokeColor = UIColor.black.cgColor
            myCircleTest.lineWidth = 2
            
    
            view.addSubview(test)
            view.addSubview(circleTest)
            view.addSubview(myTest)
            view.addSubview(myCircleTest)
    
            test.translatesAutoresizingMaskIntoConstraints = false
            circleTest.translatesAutoresizingMaskIntoConstraints = false
            myTest.translatesAutoresizingMaskIntoConstraints = false
            myCircleTest.translatesAutoresizingMaskIntoConstraints = false
    
            NSLayoutConstraint.activate([
                test.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
                test.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
                test.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -170),
                test.heightAnchor.constraint(equalToConstant: 40),
    
                circleTest.topAnchor.constraint(equalTo: test.bottomAnchor, constant: 8),
                circleTest.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                circleTest.heightAnchor.constraint(equalToConstant: 40),
                circleTest.widthAnchor.constraint(equalTo: circleTest.heightAnchor),
    
                myTest.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15),
                myTest.topAnchor.constraint(equalTo: circleTest.bottomAnchor, constant: 8),
                myTest.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -170),
                myTest.heightAnchor.constraint(equalToConstant: 40),
    
                myCircleTest.topAnchor.constraint(equalTo: myTest.bottomAnchor, constant: 8),
                myCircleTest.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                myCircleTest.heightAnchor.constraint(equalToConstant: 40),
                myCircleTest.widthAnchor.constraint(equalTo: myCircleTest.heightAnchor),
                
            ])
        }
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search