Je souhaite définir la variable UINavigationbar
backgroundColor
sur une couleur de dégradé, dans laquelle je souhaite la définir via un tableau de couleurs afin de créer un dégradé, idéalement, en tant que méthode accessible dans UINavigationBar
pour modifier la couleur de ce dégradé.
Aucune suggestion? (En plus de définir une image manuellement comme image d'arrière-plan de la barre de navigation)
Créez un calque dégradé et ajoutez-le en tant qu'arrière-plan de la barre de navigation.
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.navigationController.navigationBar.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
[self.navigationController.navigationBar setBackgroundImage:[self imageFromLayer:gradient] forBarMetrics:UIBarMetricsDefault];
Pour créer une image à partir d'un calque.
- (UIImage *)imageFromLayer:(CALayer *)layer
{
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
Une dernière chose, il existe une bibliothèque disponible dans github: CRGradientNavigationBar vous pouvez également utiliser cette bibliothèque.
Xcode 8.3.1, Swift 3.1
extension CAGradientLayer
extension CAGradientLayer {
convenience init(frame: CGRect, colors: [UIColor]) {
self.init()
self.frame = frame
self.colors = []
for color in colors {
self.colors?.append(color.cgColor)
}
startPoint = CGPoint(x: 0, y: 0)
endPoint = CGPoint(x: 0, y: 1)
}
func createGradientImage() -> UIImage? {
var image: UIImage? = nil
UIGraphicsBeginImageContext(bounds.size)
if let context = UIGraphicsGetCurrentContext() {
render(in: context)
image = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
return image
}
}
extension UINavigationBar
extension UINavigationBar {
func setGradientBackground(colors: [UIColor]) {
var updatedFrame = bounds
updatedFrame.size.height += self.frame.Origin.y
let gradientLayer = CAGradientLayer(frame: updatedFrame, colors: colors)
setBackgroundImage(gradientLayer.createGradientImage(), for: UIBarMetrics.default)
}
}
classe ViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var colors = [UIColor]()
colors.append(UIColor(red: 221/255, green: 34/255, blue: 13/255, alpha: 1))
colors.append(UIColor(red: 247/255, green: 113/255, blue: 98/255, alpha: 1))
navigationController?.navigationBar.setGradientBackground(colors: colors)
}
}
Tableau principal
Dans Swift 3 et Swift 4 :
let gradient = CAGradientLayer()
let sizeLength = UIScreen.main.bounds.size.height * 2
let defaultNavigationBarFrame = CGRect(x: 0, y: 0, width: sizeLength, height: 64)
gradient.frame = defaultNavigationBarFrame
gradient.colors = [UIColor.white.cgColor, UIColor.black.cgColor]
UINavigationBar.appearance().setBackgroundImage(self.image(fromLayer: gradient), for: .default)
Pour créer une image à partir d'une couche:
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
Dans Swift 2 :
let gradient = CAGradientLayer()
let sizeLength = UIScreen.mainScreen().bounds.size.height * 2
let defaultNavigationBarFrame = CGRectMake(0, 0, sizeLength, 64)
gradient.frame = defaultNavigationBarFrame
gradient.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]
UINavigationBar.appearance().setBackgroundImage(self.image(fromLayer: gradient), forBarMetrics: .Default)
Pour créer une image à partir d'une couche:
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.renderInContext(UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
Ceci est la solution sans utiliser une CAGradientLayer
intermédiaire, et simplement en utilisant CoreGraphics
, dans Swift 3.0.
Essentiellement, la méthode crée une UIImage
à la volée avec les couleurs de dégradé passées et la définit.
extension UINavigationBar
{
/// Applies a background gradient with the given colors
func apply(gradient colors : [UIColor]) {
var frameAndStatusBar: CGRect = self.bounds
frameAndStatusBar.size.height += 20 // add 20 to account for the status bar
setBackgroundImage(UINavigationBar.gradient(size: frameAndStatusBar.size, colors: colors), for: .default)
}
/// Creates a gradient image with the given settings
static func gradient(size : CGSize, colors : [UIColor]) -> UIImage?
{
// Turn the colors into CGColors
let cgcolors = colors.map { $0.cgColor }
// Begin the graphics context
UIGraphicsBeginImageContextWithOptions(size, true, 0.0)
// If no context was retrieved, then it failed
guard let context = UIGraphicsGetCurrentContext() else { return nil }
// From now on, the context gets ended if any return happens
defer { UIGraphicsEndImageContext() }
// Create the Coregraphics gradient
var locations : [CGFloat] = [0.0, 1.0]
guard let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: cgcolors as NSArray as CFArray, locations: &locations) else { return nil }
// Draw the gradient
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: [])
// Generate the image (the defer takes care of closing the context)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
La déclaration defer
le rend tellement plus propre que les versions précédentes . Notez que CGGradient
sont disponibles depuis iOS 8.0.
En outre, cela crée le dégradé de gauche à droite, en modifiant les paramètres de drawLinearGradient
(start
et end
) déplace les emplacements. C'est pour votre implémentation.
Pour Swift 4.2
extension UINavigationBar {
func setGradientBackground(colors: [Any]) {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.locations = [0.0 , 0.5, 1.0]
gradient.startPoint = CGPoint(x: 0.0, y: 1.0)
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
var updatedFrame = self.bounds
updatedFrame.size.height += self.frame.Origin.y
gradient.frame = updatedFrame
gradient.colors = colors;
self.setBackgroundImage(self.image(fromLayer: gradient), for: .default)
}
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
}
Comment utiliser
self.navigationController?.navigationBar.setGradientBackground(colors: [
UIColor.red.cgColor,
UIColor.green.cgColor,
UIColor.blue.cgColor
])
Dans Swift 3
let gradient = CAGradientLayer()
let sizeLength = UIScreen.main.bounds.size.height * 2
let defaultNavigationBarFrame = CGRect(x: 0, y: 0, width: sizeLength, height: 64)
gradient.frame = defaultNavigationBarFrame
gradient.colors = [UIColor.white.cgColor, UIColor.black.cgColor]
UINavigationBar.appearance().setBackgroundImage(self.image(fromLayer: gradient), for: .default)
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
La solution Objective C qui fonctionne aussi sur iPhone X:
- (void)addGradientToNavigationBar
{
CAGradientLayer *gradient = [CAGradientLayer layer];
CGRect gradientFrame = self.navigationController.navigationBar.bounds;
gradientFrame.size.height += [UIApplication sharedApplication].statusBarFrame.size.height;
gradient.frame = gradientFrame;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorGradientUp] CGColor], (id)[[UIColor colorGradientDown] CGColor], nil];
[self.navigationController.navigationBar setBackgroundImage:[self imageFromLayer:gradient] forBarMetrics:UIBarMetricsDefault];
}
- (UIImage *)imageFromLayer:(CALayer *)layer
{
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}