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.
And this image below is debug view hierarchy.
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)
])
}
}
CodePudding user response:
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:
and zoomed-in to 200%:
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:
and, again zoomed-in to 200%:
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),
])
}
}
CodePudding user response:
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.
Kind regards, MacUserT