ios - custom - Cómo ocultar UINavigationBar 1px línea de fondo
navigation item swift (30)
Tengo una aplicación que a veces necesita su barra de navegación para mezclarse con el contenido.
¿Alguien sabe cómo deshacerse de o cambiar el color de esta pequeña barra molesta?
En la imagen debajo de la situación que tengo: estoy hablando de esta línea de altura de 1px debajo de "Root View Controller"
Acabo de crear una extensión para esto ... Lo siento por el formato (esta es mi primera respuesta).
Uso:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.hideShadow = true
}
Extensión:
UINavigationController.swift
// Created by Ricardo López Rey on 16/7/15.
import Foundation
struct UINavigationControllerExtension {
static var hideShadowKey : String = "HideShadow"
static let backColor = UIColor(red: 247/255, green: 247/255, blue: 248/255, alpha: 1.0)
}
extension UINavigationController {
var hideShadow : Bool {
get {
if let ret = objc_getAssociatedObject(self, &UINavigationControllerExtension.hideShadowKey) as? Bool {
return ret
} else {
return false
}
}
set {
objc_setAssociatedObject(self,&UINavigationControllerExtension.hideShadowKey,newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
if newValue {
self.navigationBar.setBackgroundImage(solidImage(UINavigationControllerExtension.backColor), forBarMetrics: UIBarMetrics.Default)
self.navigationBar.shadowImage = solidImage(UIColor.clearColor())
} else {
self.navigationBar.setBackgroundImage(nil, forBarMetrics: UIBarMetrics.Default)
}
}
}
private func solidImage(color: UIColor, size: CGSize = CGSize(width: 1,height: 1)) -> UIImage {
var rect = CGRectMake(0, 0, size.width, size.height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(rect)
var image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Aquí hay una forma de hacerlo sin usar ninguna imagen, esta es la única manera que funcionó para mí:
self.navigationController.navigationBar.layer.shadowOpacity = 0;
Desafortunadamente, debe hacer esto en cada archivo en el que desee que no aparezca la línea. No hay manera de hacerlo de esta manera en appDelegate
.
Editar:
No es necesario configurar shadowColor
en nil
, esta es la única línea que necesitarás.
Aquí hay una solución muy simple:
self.navigationController.navigationBar.clipsToBounds = YES;
Debes agregar una vista a la parte inferior de la barra de UISearch.
let rect = searchController.searchBar.frame;
let lineView : UIView = UIView.init(frame: CGRect.init(x: 0, y: rect.size.height-1, width: rect.size.width, height: 1))
lineView.backgroundColor = UIColor.init(hexString: "8CC73E")
searchController.searchBar.addSubview(lineView)
Dentro de AppDelegate , esto ha cambiado globalmente el formato de la barra de navegación:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarPosition: UIBarPosition.Any, barMetrics: UIBarMetrics.Default)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = UIColor.redColor()
UINavigationBar.appearance().translucent = false
UINavigationBar.appearance().clipsToBounds = false
UINavigationBar.appearance().backgroundColor = UIColor.redColor()
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : (UIFont(name: "FONT NAME", size: 18))!, NSForegroundColorAttributeName: UIColor.whiteColor()] }
No he logrado implementar nada diferente en un VC específico, pero esto ayudará al 90% de las personas
Después de estudiar la respuesta de Serhil, creé una UINavigationBar+Addition que puede ocultar fácilmente la línea del cabello.
#import "UINavigationBar+Addition.h"
- (void)viewDidLoad {
[super viewDidLoad];
UINavigationBar *navigationBar = self.navigationController.navigationBar;
[navigationBar hideBottomHairline];
}
Después de todo el obstáculo, he encontrado esta solución para eliminar la línea del borde inferior de la barra de navegación.
Rápido:
self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
C objetivo:
[self.navigationController.navigationBar setValue:@(YES) forKeyPath:@"hidesShadow"];
El problema con la configuración de una imagen de fondo es que elimina el desenfoque. Puedes eliminarlo sin configurar una imagen de fondo. Vea mi respuesta here .
En Swift 3 lo hacemos así.
Para cualquier controlador de vista:
navigationBar.shadowImage = UIImage()
setBackgroundImage(UIImage(), for: .default)
Para una aplicación completa:
UINavigationBar.appearance().setBackgroundImage(UIImage(),barMetrics: .Default)
UINavigationBar.appearance().shadowImage = UIImage()
En Swift 3.0
Edite su AppDelegate.swift
agregando el siguiente código a la función de su aplicación:
// Override point for customization after application launch.
// Remove border in navigationBar
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
En iOS8, si configura UINavigationBar.barStyle
en .Black
, puede configurar el fondo de la barra como un color plano sin el borde.
En Swift:
UINavigationBar.appearance().translucent = false
UINavigationBar.appearance().barStyle = UIBarStyle.Black
UINavigationBar.appearance().barTintColor = UIColor.redColor()
Esto puede sonar estúpido, pero esta línea de cabello solo aparece cuando el color de fondo de la vista del controlador de la vista se establece en cualquier color, pero en blanco. Me sorprendió saber este hecho.
Entonces, si desea que desaparezca sin muchos problemas, simplemente configure el color de fondo de la vista del controlador en COLOR BLANCO.
La forma rápida de hacerlo:
UINavigationBar.appearance().setBackgroundImage(
UIImage(),
forBarPosition: .Any,
barMetrics: .Default)
UINavigationBar.appearance().shadowImage = UIImage()
La respuesta de pxpgraphics para Swift 3.0.
import Foundation
import UIKit
extension UINavigationBar {
func hideBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(view: self)
navigationBarImageView!.isHidden = true
}
func showBottomHairline() {
let navigationBarImageView = hairlineImageViewInNavigationBar(view: self)
navigationBarImageView!.isHidden = false
}
private func hairlineImageViewInNavigationBar(view: UIView) -> UIImageView? {
if view is UIImageView && view.bounds.height <= 1.0 {
return (view as! UIImageView)
}
let subviews = (view.subviews as [UIView])
for subview: UIView in subviews {
if let imageView: UIImageView = hairlineImageViewInNavigationBar(view: subview) {
return imageView
}
}
return nil
}
}
extension UIToolbar {
func hideHairline() {
let navigationBarImageView = hairlineImageViewInToolbar(view: self)
navigationBarImageView!.isHidden = true
}
func showHairline() {
let navigationBarImageView = hairlineImageViewInToolbar(view: self)
navigationBarImageView!.isHidden = false
}
private func hairlineImageViewInToolbar(view: UIView) -> UIImageView? {
if view is UIImageView && view.bounds.height <= 1.0 {
return (view as! UIImageView)
}
let subviews = (view.subviews as [UIView])
for subview: UIView in subviews {
if let imageView: UIImageView = hairlineImageViewInToolbar(view: subview) {
return imageView
}
}
return nil
}
}
Objetivo C respuesta a la pregunta anterior
// eliminando 1px línea de barra de navegación
[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
[[UINavigationBar appearance] setTranslucent:NO];
[[UINavigationBar appearance] setTintColor:[UIColor yourColor]];
Otra opción si desea conservar la translucidez y no desea subclasificar cada UINavigationController
en su aplicación:
#import <objc/runtime.h>
@implementation UINavigationController (NoShadow)
+ (void)load {
Method original = class_getInstanceMethod(self, @selector(viewWillAppear:));
Method swizzled = class_getInstanceMethod(self, @selector(swizzled_viewWillAppear:));
method_exchangeImplementations(original, swizzled);
}
+ (UIImageView *)findHairlineImageViewUnder:(UIView *)view {
if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {
return (UIImageView *)view;
}
for (UIView *subview in view.subviews) {
UIImageView *imageView = [self findHairlineImageViewUnder:subview];
if (imageView) {
return imageView;
}
}
return nil;
}
- (void)swizzled_viewWillAppear:(BOOL)animated {
UIImageView *shadow = [UINavigationController findHairlineImageViewUnder:self.navigationBar];
shadow.hidden = YES;
[self swizzled_viewWillAppear:animated];
}
@end
Para hacer esto, debes establecer una imagen de sombra personalizada. Pero para que se muestre la imagen de la sombra, también necesita establecer una imagen de fondo personalizada, cita de la documentación de Apple:
Para que se muestre una imagen de sombra personalizada, una imagen de fondo personalizada también debe configurarse con el método setBackgroundImage (_: for :). Si se usa la imagen de fondo predeterminada, entonces la imagen de sombra predeterminada se usará independientemente del valor de esta propiedad.
Asi que:
let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(#imageLiteral(resourceName: "BarBackground"),
for: .default)
navigationBar.shadowImage = UIImage()
Arriba está la única manera "oficial" de ocultarlo. Desafortunadamente, elimina la translucidez de la barra.
No quiero imagen de fondo, solo color.
Tienes esas opciones:
Color sólido, sin translucidez
navigationBar.barTintColor = UIColor.redColor() navigationBar.isTranslucent = false navigationBar.setBackgroundImage(UIImage(), for: .default) navigationBar.shadowImage = UIImage()
Crea una pequeña imagen de fondo llena de color y úsala.
Utilice el método ''hacky'' descrito a continuación. También mantendrá barra translúcida.
¿Cómo mantener la barra translúcida?
Para mantener la translucidez necesita otro enfoque, parece un truco pero funciona bien. La sombra que intentamos eliminar es una línea de UIImageView
algún lugar debajo de UINavigationBar
. Podemos encontrarlo y ocultarlo / mostrarlo cuando sea necesario.
Las instrucciones a continuación suponen que necesita una línea de cabello oculta solo en un controlador de su jerarquía UINavigationController
.
Declarar variable de instancia:
private var shadowImageView: UIImageView?
Agregue el método que encuentra esta sombra (línea de cabello)
UIImageView:
private func findShadowImage(under view: UIView) -> UIImageView? { if view is UIImageView && view.bounds.size.height <= 1 { return (view as! UIImageView) } for subview in view.subviews { if let imageView = findShadowImage(under: subview) { return imageView } } return nil }
Agregar / editar
viewWillAppear/viewWillDisappear
métodos:override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if shadowImageView == nil { shadowImageView = findShadowImage(under: navigationController!.navigationBar) } shadowImageView?.isHidden = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) shadowImageView?.isHidden = false }
El mismo método también debería funcionar para la UISearchBar
cabello de UISearchBar
, y (casi) cualquier otra cosa que necesite ocultar :)
Muchas gracias a @Leo Natan por la idea original!
Para usuarios de iOS 9, esto funcionó para mí. solo agrega esto:
UINavigationBar.appearance().shadowImage = UIImage()
Prueba esto:
[[UINavigationBar appearance] setBackgroundImage: [UIImage new]
forBarMetrics: UIBarMetricsDefault];
[UINavigationBar appearance].shadowImage = [UIImage new];
La imagen de abajo tiene la explicación (iOS7 NavigationBar):
Y verifique esta pregunta SO: iOS7 - Cambiar color de borde de UINavigationBar
Quería agregar la versión Swift de la respuesta de Serhii. UIBarExtension.swift
un UIBarExtension.swift
con lo siguiente:
import Foundation
import UIKit
extension UINavigationBar {
func hideBottomHairline() {
self.hairlineImageView?.isHidden = true
}
func showBottomHairline() {
self.hairlineImageView?.isHidden = false
}
}
extension UIToolbar {
func hideBottomHairline() {
self.hairlineImageView?.isHidden = true
}
func showBottomHairline() {
self.hairlineImageView?.isHidden = false
}
}
extension UIView {
fileprivate var hairlineImageView: UIImageView? {
return hairlineImageView(in: self)
}
fileprivate func hairlineImageView(in view: UIView) -> UIImageView? {
if let imageView = view as? UIImageView, imageView.bounds.height <= 1.0 {
return imageView
}
for subview in view.subviews {
if let imageView = self.hairlineImageView(in: subview) { return imageView }
}
return nil
}
}
Sé que este es un hilo antiguo, pero encontré una solución que funciona muy bien:
Subclase UINavigationBar. En su subclase UINavigationBar, invalide didAddSubview con el siguiente código:
- (void)didAddSubview:(UIView *)subview
{
[super didAddSubview:subview];
if ([subview isKindOfClass:[UIImageView class]]) {
[subview setClipsToBounds:YES];
}
}
Si solo desea usar un color sólido de la barra de navegación y lo ha configurado en su guión gráfico, use este código en su clase AppDelegate
para eliminar el borde de 1 píxel a través del proxy de apariencia:
[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc] init]
forBarPosition:UIBarPositionAny
barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
Simple solución en veloz.
let navigationBar = self.navigationController?.navigationBar
navigationBar?.setBackgroundImage(UIImage(), forBarPosition: UIBarPosition.Any, barMetrics: UIBarMetrics.Default)
navigationBar?.shadowImage = UIImage()
Swift puso esto
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
UINavigationBar.appearance().shadowImage = UIImage()
en
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
Utilizo una extensión de UINavigationBar que me permite ocultar / mostrar esa sombra usando la API de UIAppearance o seleccionar qué barra de navegación tiene que ocultar / mostrar esa sombra usando Storyboard (o código fuente). Aquí está la extensión:
import UIKit
private var flatAssociatedObjectKey: UInt8 = 0
/*
An extension that adds a "flat" field to UINavigationBar. This flag, when
enabled, removes the shadow under the navigation bar.
*/
@IBDesignable extension UINavigationBar {
@IBInspectable var flat: Bool {
get {
guard let obj = objc_getAssociatedObject(self, &flatAssociatedObjectKey) as? NSNumber else {
return false
}
return obj.boolValue;
}
set {
if (newValue) {
let void = UIImage()
setBackgroundImage(void, forBarPosition: .Any, barMetrics: .Default)
shadowImage = void
} else {
setBackgroundImage(nil, forBarPosition: .Any, barMetrics: .Default)
shadowImage = nil
}
objc_setAssociatedObject(self, &flatAssociatedObjectKey, NSNumber(bool: newValue),
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
Ahora, para deshabilitar la sombra en todas las barras de navegación que tiene que usar:
UINavigationBar.appearance().flat = true
O puedes habilitar / deshabilitar este comportamiento usando guiones gráficos:
Swift 4 // para ocultar la línea de sombra de la barra de navegación
navigationController?.navigationBar.shadowImage = UIImage()
Solución de pxpgraphics actualizada para Swift 2.0
extension UINavigationBar {
func hideBottomHairline()
{
hairlineImageViewInNavigationBar(self)?.hidden = true
}
func showBottomHairline()
{
hairlineImageViewInNavigationBar(self)?.hidden = false
}
private func hairlineImageViewInNavigationBar(view: UIView) -> UIImageView?
{
if let imageView = view as? UIImageView where imageView.bounds.height <= 1
{
return imageView
}
for subview: UIView in view.subviews
{
if let imageView = hairlineImageViewInNavigationBar(subview)
{
return imageView
}
}
return nil
}
}
extension UIToolbar
{
func hideHairline()
{
let navigationBarImageView = hairlineImageViewInToolbar(self)?.hidden = true
}
func showHairline()
{
let navigationBarImageView = hairlineImageViewInToolbar(self)?.hidden = false
}
private func hairlineImageViewInToolbar(view: UIView) -> UIImageView?
{
if let imageView = view as? UIImageView where imageView.bounds.height <= 1
{
return imageView
}
for subview: UIView in view.subviews
{
if let imageView = hairlineImageViewInToolbar(subview)
{
return imageView
}
}
return nil
}
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIImage *emptyImage = [UIImage new];
self.navigationController.navigationBar.shadowImage = emptyImage;
[self.navigationController.navigationBar setBackgroundImage:emptyImage forBarMetrics:UIBarMetricsDefault];
}
Slightly Swift Solution
func setGlobalAppearanceCharacteristics () {
let navigationBarAppearace = UINavigationBar.appearance()
navigationBarAppearace.tintColor = UIColor.white
navigationBarAppearace.barTintColor = UIColor.blue
navigationBarAppearace.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBarAppearace.shadowImage = UIImage()
}
[tabviewController.view setBackgroundColor:[UIColor blackColor]];
Lo hizo por mí [UIColor blackColor]
podría ser su color de fondo, y tabviewController
es su UITabBarController
si lo está utilizando.