swift 中的约束有问题
Constraint having issues in swift
我遇到了约束问题。我正在使用 UIBezierPath 和自动布局。我已经完成了此处给出的几乎所有内容,但问题仍未解决,这就是我发布此问题的原因。我正在使用以下函数来圆化我视图的某个角落(我使用故事板制作的)
func addShadowAndCorner(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
let shadowLayer = CAShapeLayer()
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.curvedView.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath //2
shadowLayer.fillColor = fillColor.cgColor //3
shadowLayer.shadowColor = shadowColor.cgColor //4
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = offSet //5
shadowLayer.shadowOpacity = opacity
shadowLayer.shadowRadius = shadowRadius
self.curvedView.layer.addSublayer(shadowLayer)
}
然后我调用这个函数如下
func configureView() {
self.view.backgroundColor = UIColor(named: "appBackgroundColor")
curvedView.backgroundColor = .clear
self.addShadowAndCorner(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
}
我在“override func viewDidLayoutSubviews()”中调用了上面的函数。但是对于不同 phone 大小
的约束,我没有得到预期的行为
在 iPhone 11 模拟器上 运行 时代码运行良好,屏幕截图分享如下。
但是当 运行 在 iPhone SE 模拟器上使用相同的代码时,它无法按预期工作。下面分享了 iPhone SE
的屏幕截图
storyboard 中 curvedView 的约束是。
请帮帮我。提前致谢
你应该在 didLayoutSubviews 中应用影子代码。那时你的观点知道他们的框架大小。确保你也调用 super。
注意不要每次都通过从 didLayoutSubviews 调用 addShadowAndCorner 函数来重新添加阴影子层。
通过创建自定义 UIView
子类,您将获得最可靠(和灵活)的结果。
这是一个简单的例子:
class MyCustomView: UIView {
// properties with default values
var shadowColor: UIColor = .darkGray
var offset: CGSize = .zero
var opacity: Float = 1.0
var shadowRadius: CGFloat = 0.0
var cornerRadius: CGFloat = 0.0
var corners: UIRectCorner = []
var fillColor: UIColor = .white
let shadowLayer = CAShapeLayer()
convenience init(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.init(frame: .zero)
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.corners = corners
self.fillColor = fillColor
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
layer.addSublayer(shadowLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath //2
shadowLayer.fillColor = fillColor.cgColor //3
shadowLayer.shadowColor = shadowColor.cgColor //4
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = offset //5
shadowLayer.shadowOpacity = opacity
shadowLayer.shadowRadius = shadowRadius
}
func configureView(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.corners = corners
self.fillColor = fillColor
setNeedsLayout()
}
}
然后您可以在情节提要中添加一个 UIView
,将其自定义 Class 分配给 MyCustomView
,将其连接到一个 @IBOutlet
,然后在 viewDidLoad()
:
class MyTestVC: UIViewController {
@IBOutlet var curvedView: MyCustomView!
override func viewDidLoad() {
super.viewDidLoad()
curvedView.backgroundColor = .clear
curvedView.configureView(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
}
}
现在,它会在框架发生变化时自动更新...例如在不同的设备或设备旋转时:
您可以通过如下代码创建它:
let curvedView = MyCustomView(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
并且,只需很少的努力,您就可以做到 @IBDesignable
并将您的属性配置为 @IBInspectable
... 然后,当您在 Storyboard 中布置它时,您可以直观地看到结果。
唯一棘手的 属性 是角,因为 UIRectCorner
没有直接的 @IBInspectable
选项...所以我们可以为每个角使用 Bool 属性:
@IBDesignable
class MyCustomView: UIView {
// properties with default values
@IBInspectable var shadowColor: UIColor = .darkGray
@IBInspectable var offset: CGSize = .zero
@IBInspectable var opacity: Float = 1.0
@IBInspectable var shadowRadius: CGFloat = 0.0
@IBInspectable var cornerRadius: CGFloat = 0.0
@IBInspectable var topLeft: Bool = false
@IBInspectable var topRight: Bool = false
@IBInspectable var bottomLeft: Bool = false
@IBInspectable var bottomRight: Bool = false
@IBInspectable var fillColor: UIColor = .white
private let shadowLayer = CAShapeLayer()
convenience init(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.init(frame: .zero)
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.fillColor = fillColor
self.topLeft = corners.contains(.topLeft)
self.topRight = corners.contains(.topRight)
self.bottomLeft = corners.contains(.bottomLeft)
self.bottomRight = corners.contains(.bottomRight)
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layer.addSublayer(shadowLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = .clear
var corners: UIRectCorner = UIRectCorner()
if self.topLeft { corners.insert(.topLeft) }
if self.topRight { corners.insert(.topRight) }
if self.bottomLeft { corners.insert(.bottomLeft) }
if self.bottomRight { corners.insert(.bottomRight) }
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath
shadowLayer.fillColor = self.fillColor.cgColor
shadowLayer.shadowColor = self.shadowColor.cgColor
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = self.offset
shadowLayer.shadowOpacity = self.opacity
shadowLayer.shadowRadius = self.shadowRadius
}
public func configureView(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.fillColor = fillColor
self.topLeft = corners.contains(.topLeft)
self.topRight = corners.contains(.topRight)
self.bottomLeft = corners.contains(.bottomLeft)
self.bottomRight = corners.contains(.bottomRight)
setNeedsLayout()
}
}
现在,我们在 Storyboard 中得到了这个:
我遇到了约束问题。我正在使用 UIBezierPath 和自动布局。我已经完成了此处给出的几乎所有内容,但问题仍未解决,这就是我发布此问题的原因。我正在使用以下函数来圆化我视图的某个角落(我使用故事板制作的)
func addShadowAndCorner(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
let shadowLayer = CAShapeLayer()
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.curvedView.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath //2
shadowLayer.fillColor = fillColor.cgColor //3
shadowLayer.shadowColor = shadowColor.cgColor //4
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = offSet //5
shadowLayer.shadowOpacity = opacity
shadowLayer.shadowRadius = shadowRadius
self.curvedView.layer.addSublayer(shadowLayer)
}
然后我调用这个函数如下
func configureView() {
self.view.backgroundColor = UIColor(named: "appBackgroundColor")
curvedView.backgroundColor = .clear
self.addShadowAndCorner(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
}
我在“override func viewDidLayoutSubviews()”中调用了上面的函数。但是对于不同 phone 大小
的约束,我没有得到预期的行为在 iPhone 11 模拟器上 运行 时代码运行良好,屏幕截图分享如下。
但是当 运行 在 iPhone SE 模拟器上使用相同的代码时,它无法按预期工作。下面分享了 iPhone SE
的屏幕截图storyboard 中 curvedView 的约束是。
请帮帮我。提前致谢
你应该在 didLayoutSubviews 中应用影子代码。那时你的观点知道他们的框架大小。确保你也调用 super。
注意不要每次都通过从 didLayoutSubviews 调用 addShadowAndCorner 函数来重新添加阴影子层。
通过创建自定义 UIView
子类,您将获得最可靠(和灵活)的结果。
这是一个简单的例子:
class MyCustomView: UIView {
// properties with default values
var shadowColor: UIColor = .darkGray
var offset: CGSize = .zero
var opacity: Float = 1.0
var shadowRadius: CGFloat = 0.0
var cornerRadius: CGFloat = 0.0
var corners: UIRectCorner = []
var fillColor: UIColor = .white
let shadowLayer = CAShapeLayer()
convenience init(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.init(frame: .zero)
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.corners = corners
self.fillColor = fillColor
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
layer.addSublayer(shadowLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath //2
shadowLayer.fillColor = fillColor.cgColor //3
shadowLayer.shadowColor = shadowColor.cgColor //4
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = offset //5
shadowLayer.shadowOpacity = opacity
shadowLayer.shadowRadius = shadowRadius
}
func configureView(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.corners = corners
self.fillColor = fillColor
setNeedsLayout()
}
}
然后您可以在情节提要中添加一个 UIView
,将其自定义 Class 分配给 MyCustomView
,将其连接到一个 @IBOutlet
,然后在 viewDidLoad()
:
class MyTestVC: UIViewController {
@IBOutlet var curvedView: MyCustomView!
override func viewDidLoad() {
super.viewDidLoad()
curvedView.backgroundColor = .clear
curvedView.configureView(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
}
}
现在,它会在框架发生变化时自动更新...例如在不同的设备或设备旋转时:
您可以通过如下代码创建它:
let curvedView = MyCustomView(shadowColor: .darkGray, offSet: CGSize.init(width: 3.0, height: 3.0), opacity: 0.6, shadowRadius: 8, cornerRadius: 80, corners: [.topRight, .bottomLeft], fillColor: .white)
并且,只需很少的努力,您就可以做到 @IBDesignable
并将您的属性配置为 @IBInspectable
... 然后,当您在 Storyboard 中布置它时,您可以直观地看到结果。
唯一棘手的 属性 是角,因为 UIRectCorner
没有直接的 @IBInspectable
选项...所以我们可以为每个角使用 Bool 属性:
@IBDesignable
class MyCustomView: UIView {
// properties with default values
@IBInspectable var shadowColor: UIColor = .darkGray
@IBInspectable var offset: CGSize = .zero
@IBInspectable var opacity: Float = 1.0
@IBInspectable var shadowRadius: CGFloat = 0.0
@IBInspectable var cornerRadius: CGFloat = 0.0
@IBInspectable var topLeft: Bool = false
@IBInspectable var topRight: Bool = false
@IBInspectable var bottomLeft: Bool = false
@IBInspectable var bottomRight: Bool = false
@IBInspectable var fillColor: UIColor = .white
private let shadowLayer = CAShapeLayer()
convenience init(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.init(frame: .zero)
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.fillColor = fillColor
self.topLeft = corners.contains(.topLeft)
self.topRight = corners.contains(.topRight)
self.bottomLeft = corners.contains(.bottomLeft)
self.bottomRight = corners.contains(.bottomRight)
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layer.addSublayer(shadowLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = .clear
var corners: UIRectCorner = UIRectCorner()
if self.topLeft { corners.insert(.topLeft) }
if self.topRight { corners.insert(.topRight) }
if self.bottomLeft { corners.insert(.bottomLeft) }
if self.bottomRight { corners.insert(.bottomRight) }
let size = CGSize(width: cornerRadius, height: cornerRadius)
let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
shadowLayer.path = cgPath
shadowLayer.fillColor = self.fillColor.cgColor
shadowLayer.shadowColor = self.shadowColor.cgColor
shadowLayer.shadowPath = cgPath
shadowLayer.shadowOffset = self.offset
shadowLayer.shadowOpacity = self.opacity
shadowLayer.shadowRadius = self.shadowRadius
}
public func configureView(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {
self.shadowColor = shadowColor
self.offset = offSet
self.opacity = opacity
self.shadowRadius = shadowRadius
self.cornerRadius = cornerRadius
self.fillColor = fillColor
self.topLeft = corners.contains(.topLeft)
self.topRight = corners.contains(.topRight)
self.bottomLeft = corners.contains(.bottomLeft)
self.bottomRight = corners.contains(.bottomRight)
setNeedsLayout()
}
}
现在,我们在 Storyboard 中得到了这个: