Currently I have a UIView
container situated above a UITableView
. Using the inheritance from UIScrollView
, I created an IBOutlet
of the container view's leading constraint, and adjust the constraint similar to as follows:
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)
}
For demonstration, I've set the container view's backgroundColor
to red to visually see what's happening:
I've declared a var gradientLayer = CAGradientLayer()
and added it as as a sublayer to the container view like so:
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)
}
However, the result I'm getting is as shown:
The gradient layer does not stick to the bounds of the container view and appears to be floating.
I've looked at several similar questions:
All suggests using viewDidLayoutSubviews
like so:
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
gradientLayer.frame = nameContainerView.frame
}
However the gradient layer still appears to be floating and not sticking to the constraints of the container view.
I've also tried the following to no avail:
gradientLayer.frame = nameContainerView.bounds
gradientLayer.bounds = nameContainerView.bounds
gradientLayer.frame = nameContainerView.layer.bounds
gradientLayer.frame = nameContainerView.layer.frame
How can I resolve this issue?
Pangu - If someone wants additional information in an effort to try to help you then you should probably provide the information so that they can help you. Now to your question. You can accomplish this two ways cleanly and if I could see your function probably 3.
The first would be to create a view that uses a CAGradientLayer as the backing layer and then you could apply autolayout to the Gradient View. Here is a class you could use that took me a few minutes.
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
}
}
The second is to use a transform instead of changing the constraints on the container and everything will scale proportionately. I will leave this for you to work it out if that is the way you would like to go.