如果不允许约束,如何使用其父UIView容器移动CAGradientLayer?

时间:2018-01-24 08:55:30

标签: ios swift calayer cagradientlayer

目前我的UIView容器位于UITableView之上。使用UIScrollView的继承,我创建了容器视图的前导约束的IBOutlet,并调整约束类似于以下内容:

func scrollViewDidScroll(_ scrollView: UIScrollView)
{
    if scrollView.contentOffset.y < 0
    {
        ...
        containerViewLeftConstraint.constant -= abs(scrollView.contentOffset.y) * 2
    }
    else
    {
       ...
       containerViewLeftConstraint.constant += abs(scrollView.contentOffset.y) * 2
    }
}

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
{
    resetContainerViewSize()
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView)
{
    resetContainerViewSize()
}

func resetContainerViewSize()
{
    containerViewLeftConstraint.constant = 0.0

    UIView.animate(withDuration: 0.4,
                   delay: 0.0,
                   usingSpringWithDamping: 0.7,
                   initialSpringVelocity: 0.5,
                   options: .curveEaseInOut,
                   animations: {
                    self.view.layoutIfNeeded()
                }, completion: nil)
}

为了演示,我将容器视图的backgroundColor设置为红色,以直观地看到发生了什么:

我已声明var gradientLayer = CAGradientLayer()并将其作为子图层添加到容器视图中,如下所示:

func createGradientOverlay()
{
    gradientLayer.frame = containerView.frame

    let colors = [UIColor.black.withAlphaComponent(0.5).cgColor,
                  UIColor.white.cgColor]

    gradientLayer.colors = colors
    gradientLayer.startPoint = CGPoint(x:0.0,
                               y:0.5)
    gradientLayer.endPoint = CGPoint(x:1.0, y:0.5);
    containerView.layer.addSublayer(gradientLayer)
}

然而,我得到的结果如下所示:

渐变图层不会粘贴到容器视图的边界,并且看起来是浮动的。

我看过几个类似的问题:

  1. CALayers didn't get resized on its UIView's bounds change. Why?
  2. Auto Layout constraint on CALayer IOS
  3. How to get CAShapeLayer to work with constraints with swift?
  4. How to add a CAGradientLayer to a UIView when using programmatic constraints
  5. 所有建议使用viewDidLayoutSubviews,如此:

    override func viewDidLayoutSubviews()
    {
        super.viewDidLayoutSubviews()
    
        gradientLayer.frame = nameContainerView.frame
    }
    

    然而,渐变图层似乎仍然是浮动的,并且不会影响容器视图的约束。

    我也试过以下无济于事:

    1. gradientLayer.frame = nameContainerView.bounds
    2. gradientLayer.bounds = nameContainerView.bounds
    3. gradientLayer.frame = nameContainerView.layer.bounds
    4. gradientLayer.frame = nameContainerView.layer.frame
    5. 如何解决此问题?

1 个答案:

答案 0 :(得分:1)

盘古 - 如果有人想要其他信息以试图帮助您,那么您应该提供信息以便他们可以帮助您。现在回答你的问题。你可以干净利落地完成这两种方式,如果我能看到你的功能可能是3。

第一种方法是创建一个使用CAGradientLayer作为支持层的视图,然后将自动布局应用于渐变视图。这是一个你可以使用的课,花了我几分钟。

import UIKit


class GradientBackedLayer: UIView {

    var colors : [UIColor] = [UIColor.black.withAlphaComponent(0.5),UIColor.white]{
        didSet{
            setUpGradient()
        }
    }

    var startPoint : CGPoint = CGPoint(x:0.0,y:0.5){
        didSet{
            setUpGradient()
        }
    }

    var endPoint : CGPoint = CGPoint(x:1.0, y:0.5){
        didSet{
            setUpGradient()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpGradient()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpGradient()
    }

    func setUpGradient(){
        self.backgroundColor = .clear
        let cgColors = colors.map({$0.cgColor})
        if let gradientLayer = self.layer as? CAGradientLayer{
            gradientLayer.colors = cgColors
            gradientLayer.startPoint = startPoint
            gradientLayer.endPoint = endPoint
        }
    }

    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }

}

第二种方法是使用转换而不是更改容器上的约束,一切都将按比例缩放。如果这是你想要的方式,我会留下这个让你解决。