尝试在 UIView 上圆角时出现奇怪的行为
Weird behavior when trying to round corners on UIView
现在我在 Swift3 中使用 UIView 时遇到奇怪的行为已经有好几个小时了。我只是想添加一个居中在屏幕内的 UIView,带有彩色和圆形边框。
为了方便地圆化边框,我使用了以下扩展:
extension UIView {
/**
Rounds the given set of corners to the specified radius
- parameter corners: Corners to round
- parameter radius: Radius to round to
*/
func round(corners: UIRectCorner, radius: CGFloat) {
_round(corners: corners, radius: radius)
}
/**
Rounds the given set of corners to the specified radius with a border
- parameter corners: Corners to round
- parameter radius: Radius to round to
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let mask = _round(corners: corners, radius: radius)
addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}
/**
Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border
- parameter diameter: The view's diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
layer.masksToBounds = true
layer.cornerRadius = diameter / 2
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor;
}
}
private extension UIView {
@discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
return mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
layer.addSublayer(borderLayer)
}
}
class GameViewController: UIViewController {
@IBOutlet weak var cardView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
cardView.round(corners: UIRectCorner.allCorners, radius: 5.0, borderColor: DesignHelper.defaultColor, borderWidth: 1)
}
}
我只是用正确的参数调用 myView.round(),但它没有按预期工作。
首先,当我在故事板中添加一个 UIView 时,没有尝试添加边框和颜色,我的行为是正确的。换一种说法,
my UIView is correctly centered inside the screen
但是,一旦我尝试使用 UIView 扩展并添加彩色边框,
the view is not correctly centered anymore。右边的space好像被什么东西裁剪了
我的猜测是边界或用于绘制边框的 mask/layer 的框架有问题。但是我没有找到任何可以纠正的东西。
有什么建议吗?
实际上,我在 UIViewController 的 viewDidLoad 中调用了 round 方法。然而,正如 @luk2302 所注意到的,这不是处理边界、框架等的正确位置,因为此时视图尚未完全加载。
因此,我将对 round 方法的调用移动到我的 UIViewController 的方法 viewDidLayoutSubviews 中。那工作正常!
现在我在 Swift3 中使用 UIView 时遇到奇怪的行为已经有好几个小时了。我只是想添加一个居中在屏幕内的 UIView,带有彩色和圆形边框。
为了方便地圆化边框,我使用了以下扩展:
extension UIView {
/**
Rounds the given set of corners to the specified radius
- parameter corners: Corners to round
- parameter radius: Radius to round to
*/
func round(corners: UIRectCorner, radius: CGFloat) {
_round(corners: corners, radius: radius)
}
/**
Rounds the given set of corners to the specified radius with a border
- parameter corners: Corners to round
- parameter radius: Radius to round to
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let mask = _round(corners: corners, radius: radius)
addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}
/**
Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border
- parameter diameter: The view's diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
layer.masksToBounds = true
layer.cornerRadius = diameter / 2
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor;
}
}
private extension UIView {
@discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
return mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
layer.addSublayer(borderLayer)
}
}
class GameViewController: UIViewController {
@IBOutlet weak var cardView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
cardView.round(corners: UIRectCorner.allCorners, radius: 5.0, borderColor: DesignHelper.defaultColor, borderWidth: 1)
}
}
我只是用正确的参数调用 myView.round(),但它没有按预期工作。
首先,当我在故事板中添加一个 UIView 时,没有尝试添加边框和颜色,我的行为是正确的。换一种说法, my UIView is correctly centered inside the screen
但是,一旦我尝试使用 UIView 扩展并添加彩色边框, the view is not correctly centered anymore。右边的space好像被什么东西裁剪了
我的猜测是边界或用于绘制边框的 mask/layer 的框架有问题。但是我没有找到任何可以纠正的东西。
有什么建议吗?
实际上,我在 UIViewController 的 viewDidLoad 中调用了 round 方法。然而,正如 @luk2302 所注意到的,这不是处理边界、框架等的正确位置,因为此时视图尚未完全加载。
因此,我将对 round 方法的调用移动到我的 UIViewController 的方法 viewDidLayoutSubviews 中。那工作正常!