UINavigationBar 1pxボトムラインを非表示にする方法


443

コンテンツと調和させるためにナビゲーションバーが必要になるアプリがあります。

誰かがこの迷惑な小さなバーを取り除くか色を変える方法を知っていますか?

下の画像では、「ルートビューコントローラー」の下にあるこの1ピクセルの高さのラインについて話しています。

ここに画像の説明を入力してください



ナビゲーションの高さの1pxを増やす方法は?
Suresh Durishetti

回答:


738

iOS 13の場合:

.shadowColorプロパティを使用する

このプロパティがnilであるか、クリアな色を含む場合、バーは影を表示しません

例えば:

let navigationBar = navigationController?.navigationBar
let navigationBarAppearence = UINavigationBarAppearance()
navigationBarAppearence.shadowColor = .clear
navigationBar?.scrollEdgeAppearance = navigationBarAppearence

iOS 12以下の場合:

これを行うには、カスタムシャドウイメージを設定する必要があります。ただし、影の画像を表示するには、カスタムの背景画像も設定する必要があります。Appleのドキュメントから引用してください。

カスタムシャドウ画像を表示するには、setBackgroundImage(_:for :)メソッドを使用してカスタム背景画像も設定する必要があります。デフォルトの背景画像が使用されている場合、このプロパティの値に関係なく、デフォルトの影画像が使用されます。

そう:

let navigationBar = navigationController!.navigationBar
navigationBar.setBackgroundImage(#imageLiteral(resourceName: "BarBackground"),
                                                        for: .default)
navigationBar.shadowImage = UIImage()

上記はそれを隠す唯一の「公式」な方法です。残念ながら、それはバーの半透明性を削除します。

背景画像は必要ありません。カラーだけです

次のオプションがあります。

  1. 無地、半透明なし:

    navigationBar.barTintColor = UIColor.redColor()
    navigationBar.isTranslucent = false
    navigationBar.setBackgroundImage(UIImage(), for: .default)
    navigationBar.shadowImage = UIImage()
  2. 色で満たされた小さな背景画像を作成して使用します。

  3. 以下で説明する 'hacky'メソッドを使用します。また、バーを半透明に保ちます。

バーを半透明に保つ方法は?

半透明性を維持するには、別のアプローチが必要です。ハックのように見えますが、うまく機能します。削除しようとしている影は、UIImageViewどこかのヘアラインUINavigationBarです。それを見つけて、必要に応じて非表示/表示することができます。

以下の手順では、UINavigationController階層の1つのコントローラーでのみヘアラインを非表示にする必要があると想定しています。

  1. インスタンス変数を宣言します。

    private var shadowImageView: UIImageView?
  2. この影を見つけるメソッドを追加します(ヘアライン) 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
    }
  3. viewWillAppear/viewWillDisappearメソッドの追加/編集:

    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
    }

同じ方法がUISearchBarヘアライン、および(ほとんど)非表示にする必要のあるその他のものにも機能します。

オリジナルのアイデアを@Leo Natanに感謝します!


103
また、単にのビューを設定することができますUINavigationBar:プロパティclipsToBounds = YES
cleverbit

3
@richarddas clipsToBounds = YESは魅力のように動作します!ありがとう!
romeouald 14

3
一部のレイアウトでは、clipsToBoundsが機能しない場合があります。この答えは私にはぴったりでした。私だけがUINavigationBarサブクラスを作成し、上記のコードを使用して-layoutSubviewメソッドでシャドウイメージを非表示にしました。ありがとう!
cgossain

7
iOSのトップステータスバーが半透明になり、テーブルビューがUINavigationBarの背後でスクロールするのが見えるという問題があったことに注意してください。setTranslucent = NOに設定してこれを修正しました。
Vlad

2
iOS 10では、viewWillAppear 呼び出されたときに取得できないようですshadowImageView
xi.lin

241

以下は簡単に役立ちます!

迅速:

self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")

目的C:

[self.navigationController.navigationBar setValue:@(YES) forKeyPath:@"hidesShadow"];

6
私はXcode 8とiOS 8以上の開発者で、上記以外は上記のどれも私のために機能しませんでした。
Vakas

2
XCode 8および> iOS 8でも同様です。これが私にとって有効な唯一の答えです。
cloudcal 2016

1
これは私にとってiOS 10とXcode 8.3.1で機能する唯一の短くてシンプルな答えです。ありがとう。
Vishal Sonawane

1
Objective-C: self.navigationController.navigationBar.shadowImage = [UIImage new];
Marcelo dos Santos

1
iOS 13.3.1バージョンのiPadでは、これだけが私にとっては機能します。
ラビ

145

純色のナビゲーションバーの色を使用するだけで、ストーリーボードでこれを設定した場合は、AppDelegateクラスで次のコードを使用して、外観プロキシを介して1ピクセルの境界線を削除します。

[[UINavigationBar appearance] setBackgroundImage:[[UIImage alloc] init]
                                  forBarPosition:UIBarPositionAny
                                      barMetrics:UIBarMetricsDefault];

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

2
これにより、コードベースのすべてのナビゲーションバーに対してグローバルに設定されます。たいていの場合、必要なものではありません。
Christoph

97

これを試して:

[[UINavigationBar appearance] setBackgroundImage: [UIImage new]  
                                   forBarMetrics: UIBarMetricsDefault];

[UINavigationBar appearance].shadowImage = [UIImage new];

以下の画像に説明があります(iOS7 NavigationBar):

ここに画像の説明を入力してください

そして、このSOの質問を確認してください: iOS7-UINavigationBarの境界線の色を変更してください


Serhiiが言ったように、影のイメージを受け入れるには、カスタムの背景イメージを設定する必要があります。
akashivskyy 2013年

3
これをAppDelegateで行います。
myusuf3 14

すばらしい回答...私の一日を救った_ / \ _
Akshay

@RPMはiOS 7、8、9、10で最適に動作します。Swiftのメディアには、viewControllesのナビゲーションバーと同じコードがあります。
Akhrameev 2017年

64

Serhiiの回答のSwiftバージョンを追加したかった。私UIBarExtension.swiftは次のものを作成しました:

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
    }
}

ありがとうございました!これが答えです。
PeiweiChen

これは、navigationBarで機能しますが、uitoolbarでは機能しません
uitoolbar

私はiOS 12でこれが機能していないことを発見しました。:(。
クリス・プリンス

iOS 13に対応
ttorbik

これが答えです。
iOS

63

それを行うための迅速な方法:

UINavigationBar.appearance().setBackgroundImage(
    UIImage(),
    forBarPosition: .Any,
    barMetrics: .Default)

UINavigationBar.appearance().shadowImage = UIImage()

2
最も洗練された答えを見つける前に、これをリストから遠ざけることは非常にまれです。+1!
sudo make install

3
UINavigationBar thoの背景全体を非表示にします:/
user365314

不正解です。背景全体も非表示になります。
TomSawyer

3
注:navigationBarのisTranslucentをfalseに設定する必要があります
dmathewwws

19

迅速なシンプルなソリューション

   let navigationBar = self.navigationController?.navigationBar
    navigationBar?.setBackgroundImage(UIImage(), forBarPosition: UIBarPosition.Any, barMetrics: UIBarMetrics.Default)
    navigationBar?.shadowImage = UIImage()

3
+1すべての答えの中で、これが最終的に私にとってうまくいったものです。他の回答のようにステータスバーを台無しにせず、プロジェクトのすべてのナビゲーションバーではなく、1つのナビゲーションコントローラーバーのみを変更する問題に対処します。
JoeGalind

Swift 4.2バージョン:navigationBar?.setBackgroundImage(UIImage()、for:UIBarPosition.any、barMetrics:UIBarMetrics.default)navigationBar?.shadowImage = UIImage()
airowe

16

Serhilからの回答を検討した後、ヘアラインを簡単に隠すことができるポッドUINavigationBar + Additionを作成しました。

#import "UINavigationBar+Addition.h"

- (void)viewDidLoad {
    [super viewDidLoad];

    UINavigationBar *navigationBar = self.navigationController.navigationBar;
    [navigationBar hideBottomHairline];
}

16

Swift 3.0の場合

AppDelegate.swift次のコードをアプリケーション関数に追加して、を編集します。

// Override point for customization after application launch.

// Remove border in navigationBar
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)

16

iOS 13以降、シャドウを設定または削除するシステムAPIがあります

UIKitは、shadowImageおよびshadowColorプロパティを使用して、影の外観を決定します。shadowImageがnilの場合、バーには、shadowColorプロパティの値に従って色が付けられたデフォルトの影が表示されます。shadowColorがnilであるか、clearColorカラーを含んでいる場合、バーは影を表示しません。

    let appearance = UINavigationBarAppearance()
    appearance.shadowImage = nil
    appearance.shadowColor = nil
    navigationController.navigationBar.standardAppearance = appearance

https://developer.apple.com/documentation/uikit/uibarappearance/3198009-shadowimage


shadowImageとshadowColorはUINavigationBarAppearanceヘッダーに記載されていません!! 見つけられなかった。おかげで、これで私の問題は100%解決されました
Roger Oba

1
はい、iOS 13でもうまく機能しています。@ glotchaに感謝します。
Yogesh Patel

@glotcha Right ....
Digvijay

ありがとう。私のために働いた唯一のもの
alionthego

13

ストーリーボードから非表示にすることもできます(Xcode 10.1で動作)

ランタイム属性を追加することにより:hidesShadow-ブール-True

ここに画像の説明を入力してください


11

pxpgraphicsのソリューションが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
    }

}

こんにちは、iOSを初めて使用し、自分自身を教えようとしています。拡張機能の使用方法を教えてください。私はビューコントローラーファイルを持っているので、これらの拡張機能をクラススコープの外に配置します。しかし、どのようにしてhide / showHairline()を呼び出すのですか?実際に拡張機能を使用する方法を理解していないが、そのように多くのソリューションのために使用されるが、私はちょうど彼らが実際のコードで実装されているかを理解していない
トミー・K

拡張機能は、既存のクラスに機能を追加します。拡張されたクラス、構造体、列挙型などには、これらの新機能が必要なときにいつでも使用できます。もっとここを参照してください:developer.apple.com/library/ios/documentation/Swift/Conceptual/...は
tf.alves

ええと、それで私はただ使うことができるはずUINavigationController().navigationBar/toolbar.hide/showBottomHairline()です?私はこれを試していますが、役に立ちません。私は正しく理解していませんか?
Tommy K


10

UIAppearance APIを使用してその影を非表示/表示したり、ストーリーボード(またはソースコード)を使用してその影を非表示/表示するナビゲーションバーを選択したりできるUINavigationBar拡張機能を使用しています。拡張機能は次のとおりです。

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)
        }
    }
}

ここで、使用する必要があるすべてのナビゲーションバーの影を無効にするには:

UINavigationBar.appearance().flat = true

または、ストーリーボードを使用してこの動作を有効/無効にすることができます:

ナビゲーションバーストーリーボード


@NunoGonçalvesではflatAssociatedObjectKey、関連するオブジェクトを識別するための一意のint(ポインターとして扱われる)と考えることができます。ここでは、プライベート変数のメモリアドレスによって定義されます。この変数を追加するように応答を更新しました。詳細については、nshipster.com / associated-objectsを参照してください。
Alvivi、2015年

良い解決策ですが、ナビゲーションバーがtranslucentfalseに設定されている場合にのみ機能します
ZYiOS

9

Swift 4でテストされた ONE LINEソリューション

ではViewdidload() 、キー「hidesShadow」のための真の設定ナビゲーションコントローラのuserdefault値

override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")

}

1
完璧に動作します!
Prashant Tukadiya 2018

7

スイフトはこれを置きました

UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
UINavigationBar.appearance().shadowImage = UIImage()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool

また、背景色も削除されます。
TomSawyer

7

半透明性を維持したいUINavigationControllerが、アプリのすべてをサブクラス化したくない場合の別のオプション:

#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

6
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()

}

ジェームス、ありがとう!誰かがあなたの回答に反対票を投じた理由を理解できません。
Dănuț Mihai Florian 2015

必要に応じて、次のコードを追加することもできます。 ()
Alessandro Ornano

5

Swift 4.2のソリューション

private func removeHairlineFromNavbar() {
    UINavigationBar.appearance().setBackgroundImage(
        UIImage(),
        for: .any,
        barMetrics: .default)
    UINavigationBar.appearance().shadowImage = UIImage()
}

この関数を最初のViewcontrollerに配置して呼び出すだけです viewdidload


4

iOS8では、に設定するUINavigationBar.barStyle.Black、バーの背景を境界線なしの無地の色に設定できます。

Swiftの場合:

UINavigationBar.appearance().translucent = false
UINavigationBar.appearance().barStyle = UIBarStyle.Black
UINavigationBar.appearance().barTintColor = UIColor.redColor()

これは最もクリーンなソリューションであり、これを達成するための最良の方法です。<iOS 8をサポートする必要がない場合は、この回答を使用しない理由はありません。ありがとう。
user3344977 2016

よく働く。ストーリーボードにも設定したので、コードも必要ありませんでした。
vikzilla

1
これを行うと、標準の影の代わりに非常に小さな白い線が得られます。
Vegard

4

私のために働く2行のソリューション。これをViewDidLoadメソッドに追加してみてください。

navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
self.extendedLayoutIncludesOpaqueBars = true

これだけがうまくいった
Usama bin Attique

3

これは非常に簡単な解決策です:

self.navigationController.navigationBar.clipsToBounds = YES;

37
ステータスバー領域もクリップされます。
フューリー

3

シンプルなソリューション– Swift 5

  1. 拡張機能を作成します。

    extension UIImage {
    
        class func hideNavBarLine(color: UIColor) -> UIImage? {
    
            let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
            UIGraphicsBeginImageContext(rect.size)
            let context = UIGraphicsGetCurrentContext()
            context?.setFillColor(color.cgColor)
            context?.fill(rect)
    
    
            let navBarLine = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return navBarLine
        }
    }
  2. これを追加するviewDidLoad()

    self.navigationController?.navigationBar.shadowImage = UIImage.hideNavBarLine(color: UIColor.clear)

2

iOS 9ユーザーにとって、これは私にとってはうまくいきました。これを追加するだけです:

UINavigationBar.appearance().shadowImage = UIImage()


2

UISearchBarの下部にビューを追加する必要があります

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)

これがまだ問題であるとは信じられません-もう一度遭遇しました!しかし、この解決策は現時点で可能な最良の解決策です。ありがとう@Socheat
RichAppz

1

私はこれが古いスレッドであることを知っていますが、本当にうまくいく解決策を見つけました:

UINavigationBarのサブクラス。UINavigationBarサブクラスで、didAddSubviewを次のコードでオーバーライドします。

- (void)didAddSubview:(UIView *)subview
{
    [super didAddSubview:subview];

    if ([subview isKindOfClass:[UIImageView class]]) {
        [subview setClipsToBounds:YES];
    }
}

1

私はこのための拡張機能を作成しました...フォーマットについて申し訳ありません(これが私の最初の答えです)。

使用法:

  override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.hideShadow = true
}

拡張:

 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
    }


}

1

AppDelegate内で、これによりNavBarの形式がグローバルに変更されました。

 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()] }

特定のVCに何かを実装することはできませんでしたが、これは人々の90%を助けます


1
-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    UIImage *emptyImage = [UIImage new];
    self.navigationController.navigationBar.shadowImage = emptyImage;
    [self.navigationController.navigationBar setBackgroundImage:emptyImage forBarMetrics:UIBarMetricsDefault];
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.