【问题标题】:Constraint having issues in swift约束在 swift 中出现问题
【发布时间】:2022-01-19 06:46:16
【问题描述】:

我遇到了约束问题。我正在使用 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()”中调用了上述函数。但是对于不同手机尺寸的限制,我没有得到预期的行为

代码在iPhone 11模拟器上运行良好,截图如下。

但是在 iPhone SE 模拟器上运行相同的代码时,它并没有按预期工作。下面分享了 iPhone SE 的屏幕截图

情节提要中弯曲视图的约束是。

请帮帮我。提前致谢

【问题讨论】:

  • 好像curvedView 框架是错误的。检查curvedView的布局
  • 嗨@kunwang 我已经编辑了问题以显示弯曲视图的约束和视图
  • 嗯,curvedView的宽度取决于它的SuperView,检查SuperView的布局
  • 没错。是什么限制了曲面视图的超级视图从内部调整大小?你没有足够的约束(至少你没有向我们证明你有)。

标签: ios swift autolayout constraints


【解决方案1】:

通过创建自定义 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()
    }

}

然后您可以在 Storyboard 中添加 UIView,将其自定义类分配给 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 中直观地看到结果。

唯一棘手的属性是 Corners,因为 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 中得到了这个:

【讨论】:

  • 感谢您的帮助,这件事按预期工作。非常感谢
【解决方案2】:

您应该在 didLayoutSubviews 中应用阴影代码。此时,您的视图知道它们的帧大小。确保你也调用 super。

注意不要每次都通过从 didLayoutSubviews 调用 addShadowAndCorner 函数来重新添加阴影子层。

【讨论】:

  • 我已将整个代码从函数更改为 viewDidLayoutSubview 仍然存在问题
猜你喜欢
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多