Swift: Gradient Splits on Rotation

Swift: Gradient splits on rotation

Keep in mind that when changing screen orientation all view's bounds change as well (assuming you are using auto layout) but the same thing is not applied on programmatically added layers. So in your case gradient layer still has the frame which is set based on old view bounds before rotation. To solve this I suggest subclassing your gradient view and update gradient layer frame in layoutSubviews function which is called on each view bounds change.

class GradientView: UIView {

let gradientLayer = CAGradientLayer()

override func awakeFromNib() {
gradientLayer.frame = self.bounds
gradientLayer.colors = yourColors
gradientLayer.locations = yourLocations
self.layer.addSublayer(gradientLayer)
}

override func layoutSubviews() {
gradientLayer.frame = self.bounds
}
}

Push gradient layer to background swift

You can insert a sublayer at a specific index.

self.view.layer.insertSublayer(gradientLayer, at: 0)

Applying gradient background for UIView using auto layout

You can subclass the UIView and override drawRect method where you add your gradient.

Updated to Swift 4


class GradientView: UIView {

private let gradient : CAGradientLayer = CAGradientLayer()
private let gradientStartColor: UIColor
private let gradientEndColor: UIColor

init(gradientStartColor: UIColor, gradientEndColor: UIColor) {
self.gradientStartColor = gradientStartColor
self.gradientEndColor = gradientEndColor
super.init(frame: .zero)
}

required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer)
gradient.frame = self.bounds
}

override public func draw(_ rect: CGRect) {
gradient.frame = self.bounds
gradient.colors = [gradientEndColor.cgColor, gradientStartColor.cgColor]
gradient.startPoint = CGPoint(x: 1, y: 0)
gradient.endPoint = CGPoint(x: 0.2, y: 1)
if gradient.superlayer == nil {
layer.insertSublayer(gradient, at: 0)
}
}
}

After you create your UIView you just need to add your constraints to that view.

Setting Gradient Background on UIView in Collection View Cell

The view bounds isn't yet to be known inside cellForRowAt plus it'll add many gradients when you scroll as cells are dequeued

gradientLayer.frame = bounds

So inside cell

var once = true

override func layoutSubviews() {
super.layoutSubviews()
if once {
// add gradient
once = false
}
}

OR

override func layoutSubviews() {
super.layoutSubviews()
if !(rewardsCard.layer.sublayers?.first is CAGradientLayer ) {
// add gradient
}
}

How store a tuple for NSGradient(colorsAndLocations:) in swift

Using matt's clues, I replaced the let line (using the more appropriate API init(colors:atLocations:colorSpace:)) :

let bgGradient = NSGradient(colorsAndLocations: (startColor, startPosition), (endColor, endPosition))

with

let bgGradient = NSGradient(colors: colorStopArray.map { $0.color }, atLocations: colorStopArray.map { $0.stop }, colorSpace: NSColorSpace.genericRGB)

Now it functions as I desired.



Related Topics



Leave a reply



Submit