web-dev-qa-db-fra.com

iOS7 - Changer la couleur de la bordure UINavigationBar

Est-il possible de changer la couleur grise du bas de la bordure de l'UINavigationBar dans iOS7?

J'ai déjà essayé de supprimer la bordure, mais cela ne fonctionne pas:

[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];

Merci!

28
MappleDev

Vous supprimez l'ombre mais pas la bordure, vous devez procéder comme suit:

[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];

Pour modifier la bordure, utilisez une image d'une largeur de 2 pixels:

[[UINavigationBar appearance] setShadowImage:[UIImage imageNamed:@"2pxWidthLineImage"]]; 
62
null

Voici une catégorie pour changer la couleur du bas avec la hauteur:

[self.navigationController.navigationBar setBottomBorderColor:[UIColor redColor] height:1];

enter image description here

Objectif C:

UINavigationBar + Helper.h

#import <UIKit/UIKit.h>

@interface UINavigationBar (Helper)
- (void)setBottomBorderColor:(UIColor *)color height:(CGFloat)height;
@end

UINavigationBar + Helper.m

#import "UINavigationBar+Helper.h"

@implementation UINavigationBar (Helper)

- (void)setBottomBorderColor:(UIColor *)color height:(CGFloat)height {
    CGRect bottomBorderRect = CGRectMake(0, CGRectGetHeight(self.frame), CGRectGetWidth(self.frame), height);
    UIView *bottomBorder = [[UIView alloc] initWithFrame:bottomBorderRect];
    [bottomBorder setBackgroundColor:color];
    [self addSubview:bottomBorder];
}
@end

Swift:

extension UINavigationBar {

    func setBottomBorderColor(color: UIColor, height: CGFloat) {
        let bottomBorderRect = CGRect(x: 0, y: frame.height, width: frame.width, height: height)
        let bottomBorderView = UIView(frame: bottomBorderRect)
        bottomBorderView.backgroundColor = color
        addSubview(bottomBorderView)
    }
}
55
sash

Voici une autre façon:

CALayer *border = [CALayer layer];
border.borderColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"border"]].CGColor;
border.borderWidth = 1;
CALayer *layer = self.navigationController.navigationBar.layer;
border.frame = CGRectMake(0, layer.bounds.size.height, layer.bounds.size.width, 1);
[layer addSublayer:border];
9
k06a

La seule façon que j'ai trouvée de changer de couleur est:

override func viewDidLoad() {
    super.viewDidLoad()

    if let navigationController = self.navigationController {
        let navigationBar = navigationController.navigationBar
        let navigationSeparator = UIView(frame: CGRectMake(0, navigationBar.frame.size.height - 1, navigationBar.frame.size.width, 0.5))
        navigationSeparator.backgroundColor = UIColor.redColor() // Here your custom color
        navigationSeparator.opaque = true
        self.navigationController?.navigationBar.addSubview(navigationSeparator)
    }

}
6
Luca Davanzo

J'ai écrit une extension basée sur les autres réponses pour une utilisation plus facile dans Swift:

extension UINavigationBar {

    func setBottomBorderColor(color: UIColor) {

        let navigationSeparator = UIView(frame: CGRectMake(0, self.frame.size.height - 0.5, self.frame.size.width, 0.5))
        navigationSeparator.backgroundColor = color
        navigationSeparator.opaque = true
        navigationSeparator.tag = 123
        if let oldView = self.viewWithTag(123) {
            oldView.removeFromSuperview()
        }
        self.addSubview(navigationSeparator)

    }
}

Vous pouvez utiliser cette extension en appelant la méthode dans un contexte comme celui-ci:

self.navigationController?.navigationBar.setBottomBorderColor(UIColor.whiteColor())

J'ai trouvé cela assez utile car je devais faire face à ce problème de bordure colorée.

5
FTFT1234

J'ai résolu ce problème avec l'utilisation des mises en page automatiques. La solution fonctionne sur différentes tailles d'écran et avec un changement d'orientation.

extension UINavigationBar {

    @IBInspectable var bottomBorderColor: UIColor {
        get {
            return self.bottomBorderColor;
        }
        set {
            let bottomBorderRect = CGRect.zero;
            let bottomBorderView = UIView(frame: bottomBorderRect);
            bottomBorderView.backgroundColor = newValue;
            addSubview(bottomBorderView);

            bottomBorderView.translatesAutoresizingMaskIntoConstraints = false;

            self.addConstraint(NSLayoutConstraint(item: bottomBorderView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0));
            self.addConstraint(NSLayoutConstraint(item: bottomBorderView, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 0));
            self.addConstraint(NSLayoutConstraint(item: bottomBorderView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0));
            self.addConstraint(NSLayoutConstraint(item: bottomBorderView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute,multiplier: 1, constant: 1));
        }

    }

}
5
Nikolay Khramchenko

Sur la base de la réponse de @sash, j'ai fait une extension en Swift utilisant Autolayout, expliqué ici) .

En substance, les autres solutions présentent les pièges suivants:

  • Impossible d'ajouter dropshadow si vous utilisez la solution UIImage
  • La sous-vue ajoutée ne se redimensionne pas lors de la rotation de la vue
 extension UINavigationBar {
 
 func setBottomBorderColor (couleur: UIColor, hauteur: CGFloat) -> UIView {
 
 let bottomBorderView = UIView (cadre: CGRectZero) 
 BottomBorderView.translatesAutoresizingMaskIntoConstraints = false 
 BottomBorderView.backgroundColor = color 
 
 Self.addSubview (bottomBorderView) 
 
 Permettent aux vues = ["border": bottomBorderView] 
 self.addConstraints (NSLayoutConstraint.constraintsWithVisualFormat ("H: | [border] |", options: [], mesures: nil, vues: vues)) 
 self.addConstraint (NSLayoutConstraint (item: bottomBorderView, attribut: .Height, relatedBy: .Equal, toItem: nil, attribut: .NotAnAttribute, multiplier: 1.0, constant: height)) 
 self.addConstraint (NSLayoutConstraint (item : bottomBorderView, attribut: .Bottom, relatedBy: .Equal, toItem: self, attribut: .Bottom, multiplicateur: 1.0, constant: height)) 
 
 return bottomBorderView 
} 
} 

Cela vous permet d'ajouter une ombre portée si vous en avez besoin, et cela gère bien la rotation!

4
Pierre

Si vous aimez les solutions simples et hacky comme moi, créez une vue qui couvre la bordure par défaut:

UIView *navBarLineView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.navigationController.navigationBar.frame),
                                                                  CGRectGetWidth(self.navigationController.navigationBar.frame), 1)];
navBarLineView.backgroundColor = [UIColor redColor];
[self.navigationController.navigationBar addSubview:navBarLineView];
2
budidino

budidino les solutions fonctionnent très bien. Le voici pour Swift:

let navBarLineView = UIView(frame: CGRectMake(0,
    CGRectGetHeight((navigationController?.navigationBar.frame)!),
    CGRectGetWidth((self.navigationController?.navigationBar.frame)!),
    1))

navBarLineView.backgroundColor = UIColor.whiteColor()

navigationController?.navigationBar.addSubview(navBarLineView)
1
linker

Eh bien, si vous souhaitez supprimer la bordure inférieure, vous définissez l'image d'ombre sur une image vide

[navigationBar setShadowImage:[UIImage new]];

donc, si vous voulez le définir sur une autre couleur, créez simplement une image avec cette couleur, j'utilise une fonction d'assistance pour créer une image à partir de la couleur ci-dessous (source d'origine http://jslim.net/blog/2014/05/05/ios-personnaliser-uitabbar-apparence / )

+ (UIImage *)imageFromColor:(UIColor *)color forSize:(CGSize)size 
{
return [UIImage imageFromColor:color forSize:size withCornerRadius:0];
}

+ (UIImage *)imageFromColor:(UIColor *)color forSize:(CGSize)size     withCornerRadius:(CGFloat)radius
{
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Begin a new image that will be the new image with the rounded corners
// (here with the size of an UIImageView)
UIGraphicsBeginImageContext(size);

// Add a clip before drawing anything, in the shape of an rounded rect
[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius] addClip];
// Draw your image
[image drawInRect:rect];

// Get the image, here setting the UIImageView image
image = UIGraphicsGetImageFromCurrentImageContext();

// Lets forget about that we were drawing
UIGraphicsEndImageContext();

return image;
}

et dans ma barre de navigation

[navigationBar setShadowImage:[UIImage imageFromColor:[UIColor redColor] forSize:CGSizeMake(CGRectGetWidth(self.tableView.frame), 1)]];

ça y est, ça marche pour moi, espérons cette aide. Veuillez envisager de modifier la réponse acceptée car elle ne fonctionne pas et peut être source de confusion

1
Ansel

Pour s'appuyer sur l'implémentation de @ sash Swift, vous pouvez rendre la bordure sensible aux changements de rotation/trait en utilisant des contraintes:

extension UINavigationBar {
  func setBottomBorderColor(color: UIColor, height: CGFloat) {

    let bottomBorderView = UIView()
    bottomBorderView.backgroundColor = color
    bottomBorderView.translatesAutoresizingMaskIntoConstraints = false
    addSubview(bottomBorderView)

    // Add constraints to make the bar always stay at the bottom of the nav bar and change size with rotation/trait changes
    let horizontalConstraint = NSLayoutConstraint(item: bottomBorderView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0)
    let verticalConstraint = NSLayoutConstraint(item: bottomBorderView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
    let widthConstraint = NSLayoutConstraint(item: bottomBorderView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: .width, multiplier: 1, constant: 0)
    let heightConstraint = NSLayoutConstraint(item: bottomBorderView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: height)

    self.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
  }
}
1
g0ld2k

Voici la méthode pour créer une image avec des couleurs claires:

+ (UIImage*)imageFromColor:(UIColor *)color withSize:(CGSize)sizeImage
{
    UIImage *resultImage = nil;

    UIGraphicsBeginImageContext(sizeImage);

    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), color.CGColor);
    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0.0f, 0.0f, sizeImage.width, sizeImage.height));
    resultImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return resultImage;
}

Voici son utilisation pour supprimer les résultats négatifs ennuyeux:

navigationBar.shadowImage = [UIImage imageFromColor:[UIColor clearColor] withSize:CGSizeMake(1.0f, 1.0f)];
0
Eugene Alexeev

Image 1

vous pouvez utiliser Reveal pour voir que la couleur de la bordure est la couleur de fond de UIImageView. donc en modifiant directement la couleur de fond de l'imageView ou en la masquant.

le code: j'écris dans @interface QdtTabBarController: UITabBarController

Class backGroundClass = NSClassFromString(@"_UIBarBackground");
for (UIView *view in self.tabBar.subviews) {
    if ([view isKindOfClass:backGroundClass]) {
        for (UIView *view2 in view.subviews) {
            if ([view2 isKindOfClass:[UIImageView class]]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    view2.backgroundColor = [UIColor redColor];
                });
            };
        };
        break;
    }
}

Image 2

0
Q.Man