I have an interesting issue, but I'm not sure how to solve it. I am attempting to extend UIView with an @IBInspectable. However, with this method the corner radius seems to be set from the nib files default side, not the actual size of the view.
So, when in IB I set the "View as" to iPhoneSE and build for iPhoneSE, the view is a circle. However, if I build for iPhone7, the corners are not fully rounded into a circle. Conversely, if I set "View as" to iPhone7 and build for iPhone7, the view is a circle, However, if I build for iPhoneSE the corners are over-rounded.
Pictures and code below:
Extension
extension UIView {
@IBInspectable var cornerRadius:Double {
get {
return Double(layer.cornerRadius)
}
set {
layer.cornerRadius = CGFloat(newValue)
layer.masksToBounds = newValue > 0
}
}
@IBInspectable var circleView:Bool {
get {
return layer.cornerRadius == min(self.frame.width, self.frame.height) / CGFloat(2.0) ? true : false
}
set {
if newValue {
layer.cornerRadius = min(self.frame.width, self.frame.height) / CGFloat(2.0)
layer.masksToBounds = true
}
else{
layer.cornerRadius = 0.0
layer.masksToBounds = false
}
}
}
}
"View as" set as iPhoneSE in IB
Built for iPhoneSE
Build for iPhone 7
"View as" set as iPhone7
Build for iPhone SE
Build for iPhone 7
You will only get a full circle if your view is a square.
If you're view is a rectangle and you set the cornerRadius
with a value less than half the smallest dimension, you will get the second view and if it's a value greater than that you will get the diamond shaped one.
Check your constraints and you should compute the cornerRadius
after the view finishes layout in viewDidLayout
so you get the correct size.
Here is a Playground showing this (I've added an animation to show better the issue):
import UIKit
import PlaygroundSupport
extension UIView
{
func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval)
{
let animation = CABasicAnimation(keyPath:"cornerRadius")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.fromValue = from
animation.toValue = to
animation.duration = duration
self.layer.add(animation, forKey: "cornerRadius")
self.layer.cornerRadius = to
}
}
let v = UIView(frame: CGRect(x: 0, y: 0, width: 350, height: 450))
PlaygroundPage.current.liveView = v
let squareView = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
squareView.backgroundColor = .red
squareView.layer.masksToBounds = true
v.addSubview(squareView)
var cornerRadius = CGFloat(0.5*min(squareView.frame.width,
squareView.frame.height))
squareView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5)
let rectangleView = UIView(frame: CGRect(x: 10, y: 200, width: 100, height: 200))
rectangleView.backgroundColor = .blue
rectangleView.layer.masksToBounds = true
v.addSubview(rectangleView)
cornerRadius = CGFloat(0.5*min(rectangleView.frame.width,
rectangleView.frame.height))
rectangleView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5)
let diamondView = UIView(frame: CGRect(x: 200, y: 200, width: 100, height: 200))
diamondView.backgroundColor = .green
diamondView.layer.masksToBounds = true
v.addSubview(diamondView)
cornerRadius = CGFloat(0.5*max(diamondView.frame.width,
diamondView.frame.height))
diamondView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5)