จะลบเส้นขอบของ navigationBar อย่างรวดเร็วได้อย่างไร?


131

ฉันพยายามลบเส้นขอบ navigationBars โดยไม่มีโชค ฉันได้ค้นคว้าและดูเหมือนว่าผู้คนจะบอกให้ตั้งค่า shadowImage และ BackgroundImage เป็นศูนย์ แต่สิ่งนี้ไม่ได้ผลในกรณีของฉัน

รหัสของฉัน

    self.navigationController?.navigationBar.barTintColor = UIColor(rgba: "#4a5866")
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
    self.navigationController?.navigationBar.shadowImage = UIImage(named: "")

ภาพประกอบ:

ใส่คำอธิบายภาพที่นี่

คำตอบ:


309

ปัญหาอยู่ที่สองบรรทัดนี้:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage(named: "")

เนื่องจากคุณไม่มีรูปภาพที่ไม่มีชื่อให้UIImage(named: "")ส่งคืนnilซึ่งหมายถึงพฤติกรรมเริ่มต้นที่เริ่มต้น:

เมื่อไม่มีศูนย์ภาพเงาที่กำหนดเองจะแสดงแทนภาพเงาเริ่มต้น เพื่อให้แสดงเงาที่กำหนดเองต้องตั้งค่าภาพพื้นหลังแบบกำหนดเองด้วย -setBackgroundImage: forBarMetrics: (หากใช้ภาพพื้นหลังเริ่มต้นระบบจะใช้ภาพเงาเริ่มต้น)

คุณต้องการภาพที่ว่างเปล่าอย่างแท้จริงดังนั้นเพียงแค่เริ่มต้นด้วยUIImage():

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()

2
คำตอบนี้ได้ผลจริงๆ เนื่องจากหากใช้คำตอบที่ยอมรับ (รหัส) แถบเครื่องมือจะลบ imageViews เป็น
Sergey Krasiuk

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ยังใช้งานได้เมื่อตั้งค่าจาก UINavigationBar.appearance ()
Heinrisch

1
นี่ควรเป็นคำตอบที่ยอมรับสำหรับ Swift 3 คำตอบที่ยอมรับได้สำหรับฉันใน Swift 2 แต่ไม่ใช่ใน Swift 3
ColinMasters

1
สำหรับ swift3 คุณควรเขียนวิธีที่แตกต่างกันเล็กน้อย: self.navigationController? .navigationBar.setBackgroundImage (UIImage () สำหรับ: UIBarMetrics.default) self.navigationController? .navigationBar.shadowImage = UIImage ()
Chetan Dobariya

5
วิธีนี้ขัดแย้งกับชื่อขนาดใหญ่ใน iOS 11
SteffenK

53

Swift 4 และ Swift 5

การลบเส้นขอบ:

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.layoutIfNeeded()

การกู้คืนเส้นขอบ:

self.navigationController?.navigationBar.setBackgroundImage(nil, for:.default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.layoutIfNeeded()

2
คำตอบที่สมบูรณ์แบบ :)
PJR

เราต้องการ layoutIfNeeded () ที่นี่หรือไม่?
korgx9

1
ใช่ korgx9 เราต้องการมัน มิฉะนั้นจะไม่เปลี่ยนสีจนกว่าจะจับฉลากครั้งต่อไป
Sazzad Hissain Khan

37

สิ่งนี้จะลบภาพเงาออกทั้งหมด

for parent in self.navigationController!.navigationBar.subviews {
 for childView in parent.subviews {
     if(childView is UIImageView) {
         childView.removeFromSuperview()
     }
 }
}

1
คุณช่วยอธิบายได้ไหม?
Kmeixner

1
สำหรับฉันก็ใช้วิธีนี้เช่นกันในขณะที่คำตอบของ @Nate Cook ไม่ได้ผล : S
Luca Davanzo

2
Sheist ศักดิ์สิทธิ์ !! หลังจากการค้นหาทั้งหมดนี่เป็นเพียงสิ่งเดียวที่ได้ผล
Tuan Anh Vu

มันใช้งานได้ แต่ฉันมีไอคอนเมนูในแถบนำทางและมันก็หายไป: / ฉันแค่ต้องการให้เส้นขอบถูกลบ ความช่วยเหลือ: /
Stephy Samaniego

สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่หลังจากกด ViewController ใหม่มันจะลบบรรทัดจากที่นั่นไปที่ ฉันจะป้องกันได้อย่างไร?
Anirudha Mahale

36

ด้วย Swift 2 คุณสามารถทำได้ด้วยวิธีนี้:

ไฟล์ AppDelegate

แอปพลิเคชันภายใน func (... , didFinishLaunchingWithOptions launchOptions: ... )

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarMetrics: .Default)

สำหรับ Swift 3:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)

คำตอบที่ถูกต้อง
เอ็ด.

นี่คือคำตอบที่ครอบคลุม!
madeny

ดีกว่าที่จะเขียนค่าเริ่มต้นที่มีประโยชน์เช่นนี้ที่ Appdelegate แทนที่จะเขียนในสถานที่แปลก ๆ คำตอบที่ถูกต้อง :)
Md Rais

35

เพียงเขียนสิ่งนี้ในส่วนขยายของ UINavigationBar

extension UINavigationBar {

    func shouldRemoveShadow(_ value: Bool) -> Void {
        if value {
            self.setValue(true, forKey: "hidesShadow")
        } else {
            self.setValue(false, forKey: "hidesShadow")
        }
    }
}

และใน viewController ของคุณ ...

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.shouldRemoveShadow(true)        
}

และหากต้องการยกเลิกการดำเนินการนี้สำหรับ viewController ใด ๆ ให้ส่งเท็จ


วิธีนี้ใช้งานได้ดี แต่จะซ่อนถ้าสำหรับ ALL vcs บน nav stack หากคุณใช้ใน vc1 และ vc1 สามารถพุชไปที่ vc2 ได้มันจะถูกซ่อนไว้ใน vc2 ด้วย หากต้องการแสดงเงาใน vc2 คุณจะต้องตั้งค่าเป็นเท็จใน viewDidLoad ปัญหาคือเมื่อคุณกลับไปที่ vc1 มันจะแสดงอีกครั้งเนื่องจากถูกรีเซ็ตใน vc2 คุณต้องใช้ตรรกะในการกลับไปกลับมาซึ่งอาจไม่คุ้มค่า อย่างไรก็ตามหากคุณไม่ต้องการให้ภาพเงาแสดงบน vcs ใด ๆ เลยนี่เป็นวิธีที่ง่ายที่สุดที่จะไป
Lance Samaria

สมมติว่าเรามี viewControllers ซ้อนกับ viewControllers 5 ตัว (และเราซ่อนเงาไว้ในอันแรก) ตอนนี้สำหรับ viewController ที่ 3 เท่านั้นฉันไม่ต้องการซ่อนเงาดังนั้นฉันจะเรียกเมธอดนั้นด้วย FALSE ใน viewWillAppear และด้วย TRUE ใน viewWillDisappear ของมุมมองที่ 3 นั่นคือทั้งหมดที่ต้องใช้!
Gaurav Chandarana

ของคุณถูกต้องคิดดี! อย่าคิดว่าฉันเคาะคำตอบของคุณเพราะมันรวบรัดและมีประสิทธิภาพมากฉันก็โหวตด้วยเช่นกัน ฉันใช้มันเพื่อลบมัน & navBar สำหรับข้อความแสดงข้อผิดพลาด ปัญหาที่ฉันพบคือเมื่อลบออกใน vc1 แต่แสดงเป็น vc2 แต่หากมีข้อผิดพลาดใน vc2 การลบออกใน viewWillDisappear อาจไม่ทำงาน แต่อีกครั้งมันเป็นสถานการณ์ที่ไม่เหมือนใคร ฉันชอบแนวคิด viewWillDisappear สำหรับการใช้งานกรณีทั่วไปและคุณควรเพิ่มเข้าไปในคำตอบของคุณ ไม่ว่าโค้ดของคุณจะทำงานได้และเป็นวิธีง่ายๆในการลบเงา! 👍🏿👍🏿
Lance Samaria

ใช้งานได้เหมือนมีเสน่ห์ แค่อยากให้แน่ใจว่านี่ไม่ใช่การตั้งค่าส่วนตัว?
inokey

2
นี่คือคำตอบที่ดีเยี่ยม! ฉันได้เพิ่มคำตอบที่ทำให้โค้ดมีความคล่องตัว
Scott Gardner

13

ตั้งค่าbarStyleเป็น.Blackก่อนการตั้งค่าสี:

self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()

มันสุ่มว่ามันใช้งานได้จริงหรือ? หรือฉันคิดมากไป?
joe

@joe ดีมันทำงานที่นี่ :-) มันไม่ได้ผลสำหรับคุณ?
gpbl

นั่นคือสิ่งที่มันได้ผล ฉันแค่สงสัยว่ามีคำอธิบายว่าทำไมถึงเปลี่ยน barStyle เป็นสีดำแล้วเปลี่ยนทั้ง barTintColor เป็นสีน้ำเงิน :)
joe

อาจตั้งค่าเป็นสีดำและทึบแสงมันจะปิดบางเลเยอร์ / มุมมองในแถบนำทาง ...
gpbl

ฉันลองใช้สิ่งนี้และมันจะลบบรรทัดล่าง แต่ถ้าใช้แถบสีขาวจะมองไม่เห็นชื่อ: /
RileyDev

11

สวิฟต์ 5

เมื่อใช้ setBackgroundImage / shadowImage เพื่อซ่อนเส้นขนจะมีความล่าช้าเล็กน้อย วิธีนี้จะขจัดความล่าช้า เครดิตกิ้งก่ากรอบ นี่คือวิธีที่พวกเขาใช้ (ใน ObjC)


extension UINavigationController {
    func hideHairline() {
        if let hairline = findHairlineImageViewUnder(navigationBar) {
            hairline.isHidden = true
        }
    }
    func restoreHairline() {
        if let hairline = findHairlineImageViewUnder(navigationBar) {
            hairline.isHidden = false
        }
    }
    func findHairlineImageViewUnder(_ view: UIView) -> UIImageView? {
        if view is UIImageView && view.bounds.size.height <= 1.0 {
            return view as? UIImageView
        }
        for subview in view.subviews {
            if let imageView = self.findHairlineImageViewUnder(subview) {
                return imageView
            }
        }
        return nil
    }
}

1
FWIW นี่เป็นโซลูชันเดียวที่ใช้ได้กับฉันบน iOS 13.4 ...
kevinstueber

9

คำตอบของ Luca Davanzo นั้นยอดเยี่ยม แต่ใช้ไม่ได้ใน iOS 10 ฉันแก้ไขให้ใช้งานได้ใน iOS 10 และต่ำกว่า

for parent in navigationController!.view.subviews {
    for child in parent.subviews {
        for view in child.subviews { 
            if view is UIImageView && view.frame.height == 0.5 {
                view.alpha = 0
            }
        }
    }
}

คุณยังสามารถขยาย UINavigationController และเรียกสิ่งนี้ออกจากสิ่งนั้นได้ removeFromSuperview()ในบรรทัดจะไม่ทำงานบน iOS 10 ดังนั้นฉันจึงตั้งค่าอัลฟาเป็น 0 เพื่อให้การโทรนี้เข้ากันได้ทุกที่


จับได้ดีวิธีใดในการแสดง / ซ่อนเงาในบาง viewControllers ขณะนำทาง?
Ashkan.H

คุณควรตรวจสอบความสูงที่มีheight >= 1.0. ใน iPhone รุ่นที่มีหน้าจอเรตินา 3x (เช่น 8 Plus, XR ... ) เส้นขนมีความสูง 0.33
fl034

7

ในการลบเส้นขอบออกจาก UINavigationBar ใน Swift 3+ ให้ใช้:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
UINavigationBar.appearance().isTranslucent = false

5

เพื่อความรวดเร็ว 3

ในviewDidLoadวิธีการ

navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()



2

นี่เป็นวิธีที่หากคุณต้องการทำโดยไม่เปลี่ยนสีพื้นหลัง:

// Remove the border ImageView from the NavigationBar background
func hideBottomBorder() {
    for view in navigationBar.subviews.filter({ NSStringFromClass($0.dynamicType) == "_UINavigationBarBackground" }) as [UIView] {
        if let imageView = view.subviews.filter({ $0 is UIImageView }).first as? UIImageView {
            imageView.removeFromSuperview()
        }
    }
}

หมายเหตุ: สิ่งนี้อาจขัดข้องในแอปที่ใช้งานจริง เห็นได้ชัดว่า NavigationBar ไม่ชอบให้มุมมองหายไป


2

คำตอบที่ยอมรับได้ผลสำหรับฉัน แต่ฉันสังเกตเห็นเมื่อฉันต้องการให้ภาพเงาปรากฏขึ้นอีกครั้งเมื่อย้อนกลับหรือผลักไปข้างหน้าไปยัง vc อื่นมีการกะพริบที่เห็นได้ชัดเจนในแถบนำทาง

การใช้วิธีนี้navigationController?.navigationBar.setValue(true, forKey: "hidesShadow") ใน viewWillAppear แถบเงาจะซ่อนอยู่ในตัวควบคุมมุมมองที่มองเห็นในปัจจุบัน

โดยใช้ 2 วิธีนี้

navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")

ในมุมมอง WillDis ปรากฏการกะพริบยังคงเกิดขึ้น แต่เฉพาะเมื่อภาพเงาปรากฏขึ้นอีกครั้งและไม่ใช่แถบนำทาง

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // 1. hide the shadow image in the current view controller you want it hidden in
    navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
    navigationController?.navigationBar.layoutIfNeeded()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(true)

    // 2. show the shadow image when pushing or popping in the next view controller. Only the shadow image will blink
    navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
    navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")
    navigationController?.navigationBar.layoutIfNeeded()
}

1

สำหรับ swift3 คุณควรเขียนวิธีที่แตกต่างกันเล็กน้อย:

 self.navigationController?.navigationBar.setBackgroundImage(UIImage(),
    for: UIBarMetrics.default)
   self.navigationController?.navigationBar.shadowImage = UIImage()


1

ผู้แทนแอป

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()

1

หากคุณต้องการลบเฉพาะบรรทัดล่างสุดและคงสีของ navigationBar ไว้ให้เพิ่มบรรทัดของโค้ดเหล่านี้ใน viewDidLoad: Swift 3, 4:

navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = false

ความสงบ!


0

เส้นขอบคือ UIImageView และการลบมุมมองย่อยซึ่งเป็น imageView จะลบ barButtonItems ด้วย UIImageView โค้ดด้านล่างจะช่วยคุณลบออก หวังว่านี่จะช่วยคนที่ประสบปัญหาเหมือนฉัน

for parent in self.navigationController!.navigationBar.subviews {
        for childView in parent.subviews {
            if childView.frame.height == 0.5 {
                childView.removeFromSuperview()
            }
        }
    }

UIImageView เส้นขอบมีความสูงเพียง 0.5 ดังนั้นโค้ดนี้จึงลบเฉพาะส่วนนั้น


สิ่งนี้ทำให้เกิดข้อขัดข้องสำหรับฉัน ฉันคิดว่ามุมมองของผู้ปกครองและเด็กจำเป็นต้องคลายออกในกรณีที่ไม่มีค่าว่างก่อนที่จะตรวจสอบแต่ละรายการ ฉันใช้ UINavigationController ที่กำหนดเองดังนั้นนี่อาจไม่ใช่กรณีสำหรับผู้ใช้รายอื่นที่มีแถบมาตรฐาน
Natalia

0

ภายใน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%


UINavigationBar.appearance (). backgroundColor = UIColor.redColor () ไม่จำเป็น
sabiland

0

นี่คือคำตอบในคำตอบของ Nate Cook 3 ฐานที่รวดเร็ว

   self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    self.navigationController?.navigationBar.shadowImage = UIImage()

0

iOS 11 และ Swift 4คุณควรลองทำตามหากคุณต้องการลบเส้นขอบออก แต่อย่าทำให้แถบนำทางโปร่งแสง
self.navigationBar.shadowImage = UIImage()


0

ในการนำทางที่กำหนดเองของคุณตัวควบคุมเพิ่มบรรทัดเหล่านี้:

self.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.layoutIfNeeded()

โน๊ตสำคัญ

บรรทัดสุดท้ายมีความสำคัญหากคุณใช้เมธอด viewDidLoad () บรรทัดแรกเนื่องจาก navigationController ควรวาดแถบนำทางใหม่ แต่คุณสามารถใช้สิ่งนี้ได้โดยไม่ต้องใช้ layoutIfNeeded () ในเมธอด viewWillAppear () ก่อนที่จะดึงแถบนำทาง


0

วิธีที่รวดเร็วของ Jack Chen:

extension UINavigationController {

    var isHiddenHairline: Bool {
        get {
            guard let hairline = findHairlineImageViewUnder(navigationBar) else { return true }
            return hairline.isHidden
        }
        set {
            if let hairline = findHairlineImageViewUnder(navigationBar) {
                hairline.isHidden = newValue
            }
        }
    }

    private func findHairlineImageViewUnder(_ view: UIView) -> UIImageView? {
        if view is UIImageView && view.bounds.size.height <= 1.0 {
            return view as? UIImageView
        }

        for subview in view.subviews {
            if let imageView = self.findHairlineImageViewUnder(subview) {
                return imageView
            }
        }

        return nil
    }
}

โดยใช้:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.isHiddenHairline = true
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.isHiddenHairline = false
    }

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.