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
Realm + Nstableview + Nsarraycontroller
Completion Handler in For/In Loop - Swift
Validate Unicode Code Point in Swift
Call Function on App Termination in Swift
Updating Existing Constraints Does Not Work, Wrong Use of .Active Property
Uicollectionview + Nsfetchedresultscontroller in Swift 3
Uislider Handle Changes Width on Different Size Ipads
Working Out The Start and End of a Day. Swift
How to Keep Nsmenuitem Selected in a Nspopover with Nsmenu
Realitykit - Updating Entity's Translation Returns Unexpected Values
Prefix(_ Maxlength:) Is Type-Erased When Used with a Struct That Conforms to Lazysequenceprotocol
How Make Polygon Without Intersection in Swift
How to Draw Something on a PDF in Swift