ios - navigation bar title color
¿Cómo puedo configurar la barra de navegación UIN con color degradado? (11)
Quiero establecer el
UINavigationbar
backgroundColor
la
UINavigationbar
en un color de degradado donde me gustaría establecerlo a través de una matriz de colores para crear un degradado, idealmente, como métodos accesibles dentro de
UINavigationBar
para cambiar su color a este degradado.
¿Alguna sugerencia? (Además de configurar una imagen manualmente como imagen de fondo de la barra de navegación)
Swift 5
- Incluye barra de estado en gradiente.
- No usa una imagen.
- Utiliza la transparencia para que el contenido sea visible a través de la barra de navegación.
extension UINavigationBar {
func addGradient(_ toAlpha: CGFloat, _ color: UIColor) {
let gradient = CAGradientLayer()
gradient.colors = [
color.withAlphaComponent(toAlpha).cgColor,
color.withAlphaComponent(toAlpha).cgColor,
color.withAlphaComponent(0).cgColor
]
gradient.locations = [0, 0.8, 1]
var frame = bounds
frame.size.height += UIApplication.shared.statusBarFrame.size.height
frame.origin.y -= UIApplication.shared.statusBarFrame.size.height
gradient.frame = frame
layer.insertSublayer(gradient, at: 1)
}
}
Detalles
- Xcode 10.2 (10E125)
- Swift 5
Código
extensión CAGradientLayer
import UIKit
extension CAGradientLayer {
enum Point {
case topRight, topLeft
case bottomRight, bottomLeft
case custion(point: CGPoint)
var point: CGPoint {
switch self {
case .topRight: return CGPoint(x: 1, y: 0)
case .topLeft: return CGPoint(x: 0, y: 0)
case .bottomRight: return CGPoint(x: 1, y: 1)
case .bottomLeft: return CGPoint(x: 0, y: 1)
case .custion(let point): return point
}
}
}
convenience init(frame: CGRect, colors: [UIColor], startPoint: CGPoint, endPoint: CGPoint) {
self.init()
self.frame = frame
self.colors = colors.map { $0.cgColor }
self.startPoint = startPoint
self.endPoint = endPoint
}
convenience init(frame: CGRect, colors: [UIColor], startPoint: Point, endPoint: Point) {
self.init(frame: frame, colors: colors, startPoint: startPoint.point, endPoint: endPoint.point)
}
func createGradientImage() -> UIImage? {
defer { UIGraphicsEndImageContext() }
UIGraphicsBeginImageContext(bounds.size)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
render(in: context)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
extensión UINavigationBar
import UIKit
extension UINavigationBar {
func setGradientBackground(colors: [UIColor], startPoint: CAGradientLayer.Point = .topLeft, endPoint: CAGradientLayer.Point = .bottomLeft) {
var updatedFrame = bounds
updatedFrame.size.height += self.frame.origin.y
let gradientLayer = CAGradientLayer(frame: updatedFrame, colors: colors, startPoint: startPoint, endPoint: endPoint)
setBackgroundImage(gradientLayer.createGradientImage(), for: UIBarMetrics.default)
}
}
Uso
clase ViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let colors: [UIColor] = [.red, .white]
navigationController?.navigationBar.setGradientBackground(colors: colors)
//navigationController?.navigationBar.setGradientBackground(colors: colors, startPoint: .bottomLeft, endPoint: .topRight)
}
}
Main.storyboard
Resultado
Cree una capa de degradado y agréguela como fondo de la barra de navegación.
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];
Para crear imagen a partir de capa.
- (UIImage *)imageFromLayer:(CALayer *)layer
{
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
Una cosa más, hay una biblioteca disponible en github: CRGradientNavigationBar también puede usar esta biblioteca.
En Swift 3 y 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)
Para crear una imagen desde la capa:
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
En 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)
Para crear una imagen desde la capa:
func image(fromLayer layer: CALayer) -> UIImage {
UIGraphicsBeginImageContext(layer.frame.size)
layer.renderInContext(UIGraphicsGetCurrentContext()!)
let outputImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return outputImage!
}
En 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!
}
Esta es la solución sin usar un
CAGradientLayer
intermedio, y solo usando
CoreGraphics
, en Swift 3.0.
Esencialmente, el método crea un
UIImage
sobre la marcha con los colores degradados pasados y lo establece.
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 declaración de
defer
hace que esto sea mucho más limpio que las versiones anteriores.
Tenga en cuenta que
CGGradient
está disponible desde iOS 8.0.
Además, esto crea el gradiente de izquierda a derecha, ajustando los parámetros de
drawLinearGradient
(
start
y
end
) mueve las ubicaciones.
Esto depende de su implementación.
Este es un marco para diferentes componentes de la interfaz de usuario que incluyen la barra de navegación UIN: ingrese la descripción del enlace aquí
primero: luego en su ViewController raíz que se incrustó en un UINavigationController
import SHNDStuffs
poner esto en su ViewDidLoad ()
class RootViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
SHNDNavigationBarGradient(firstColor: .darkGray,
secondColor: .white,
tintColor: .black,
isHorizontal: true)
}
Este increíble tutorial de Lawrence Tan muestra cómo establecer un degradado usando
barTintColor
y sin
backgroundImage
:
https://medium.com/swift2go/add-gradient-to-navigation-bar-in-swift-9284fe91fea2
Resumen
Extensión
CAGradientLayer
extension CAGradientLayer {
class func primaryGradient(on view: UIView) -> UIImage? {
let gradient = CAGradientLayer()
let flareRed = UIColor(displayP3Red: 241.0/255.0, green: 39.0/255.0, blue: 17.0/255.0, alpha: 1.0)
let flareOrange = UIColor(displayP3Red: 245.0/255.0, green: 175.0/255.0, blue: 25.0/255.0, alpha: 1.0)
var bounds = view.bounds
bounds.size.height += UIApplication.shared.statusBarFrame.size.height
gradient.frame = bounds
gradient.colors = [flareRed.cgColor, flareOrange.cgColor]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 0)
return gradient.createGradientImage(on: view)
}
private func createGradientImage(on view: UIView) -> UIImage? {
var gradientImage: UIImage?
UIGraphicsBeginImageContext(view.frame.size)
if let context = UIGraphicsGetCurrentContext() {
render(in: context)
gradientImage = UIGraphicsGetImageFromCurrentImageContext()?.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch)
}
UIGraphicsEndImageContext()
return gradientImage
}
}
Aplicar el gradiente
guard
let navigationController = navigationController,
let flareGradientImage = CAGradientLayer.primaryGradient(on: navigationController.navigationBar)
else {
print("Error creating gradient color!")
return
}
navigationController.navigationBar.barTintColor = UIColor(patternImage: flareGradientImage)
Solución Objective C que también funciona en 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;
}
Para 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!
}
}
Cómo utilizar
self.navigationController?.navigationBar.setGradientBackground(colors: [
UIColor.red.cgColor,
UIColor.green.cgColor,
UIColor.blue.cgColor
])
SWIFT 5
Para hacer el fondo degradado horizontal de la barra de navegación junto con la barra de estado también ... simplemente ponga este código en el método
viewDidLoad()
su controlador de
viewDidLoad()
.
self.navigationItem.title = "Gradiant Back Ground"
let gradientLayer = CAGradientLayer()
var updatedFrame = self.navigationController!.navigationBar.bounds
updatedFrame.size.height += UIApplication.shared.statusBarFrame.size.height
gradientLayer.frame = updatedFrame
gradientLayer.colors = [UIColor.green.cgColor, UIColor.blue.cgColor] // start color and end color
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0) // Horizontal gradient start
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0) // Horizontal gradient end
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.navigationController!.navigationBar.setBackgroundImage(image, for: UIBarMetrics.default)
El gradiente de salida se verá así.
¡ACLAMACIONES!