รับความสูงของแถบนำทางโดยทางโปรแกรม


131

ฉันรู้ว่าการมีอยู่ของตัวควบคุมมุมมองเพิ่มเติม (แถบการนำทาง) ผลัก UIView ลงตามความสูง ฉันก็รู้ว่าความสูงนี้ = 44px [self.view].frame.origin.y = 0ฉันได้ค้นพบว่าการผลักดันลงนี้รักษา

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

หรือรุ่นที่สั้นกว่าฉันจะทราบได้อย่างไรว่า UIView ของฉันแสดงพร้อมแถบนำทางด้านบน


หลอดไฟเริ่มเข้ามา น่าเสียดายที่ฉันไม่ได้ค้นพบวิธีที่เหมือนกันในการแก้ไขปัญหาดังที่อธิบายไว้ด้านล่าง

ฉันเชื่อว่าปัญหาทั้งหมดของฉันมุ่งเน้นไปที่งานรับอัตโนมัติของฉัน และเหตุผลที่ฉันได้ข้อสรุปว่ามีอาการเดียวกันอยู่โดยมีหรือไม่มี UIWebView และอาการนั้นก็คือทุกอย่างนั้นมีสีพีชสำหรับรูปคน สำหรับแนวนอน UIButton ส่วนใหญ่ที่อยู่ด้านล่างจะปรากฏขึ้นด้านหลัง TabBar

ตัวอย่างเช่นฉันมี UIView หนึ่งรายการจากบนลงล่าง:

UIView - ทั้งชุดสปริง (ตัวพิมพ์ดีฟอลต์) และไม่มี struts

UIScrollView - ถ้าฉันตั้งค่าสปริงทั้งสองและล้างทุกอย่างอื่น (เช่น UIView) UIButton จะบุกรุกวัตถุบนเหนือมันทันที หากฉันล้างทุกอย่าง UIButton จะใช้ได้ แต่สิ่งที่ซ่อนอยู่ด้านบนสุดด้านหลัง StatusBar การตั้งค่าเฉพาะ strut ด้านบน UIButton จะปรากฏขึ้นด้านหลัง Tab Bar

UILabel และ UIImage ติดตั้งในแนวตั้ง - แนวดิ่งบนสุดยืดหยุ่นได้ทุกที่

เพียงเพื่อให้ภาพสมบูรณ์สำหรับคนที่มี UIWebView:

UIWebView - Struts: ด้านบนซ้ายขวาสปริง: ทั้งคู่

UIButton - ไม่ได้ตั้งค่าใด ๆ เช่นยืดหยุ่นทุกที่

แม้ว่าหลอดไฟของฉันจะสลัว แต่ก็มีความหวัง


กรุณาอดทนกับฉันเพราะฉันต้องการห้องพักมากกว่าที่ให้ไว้สำหรับความคิดเห็นตอบสั้น ๆ

ขอบคุณที่พยายามเข้าใจสิ่งที่ฉันกำลังตกปลาเพื่อ ... ไปเลย

1) แต่ละ UIViewController (แอพ TabBar) มี UIImage ข้อความและอะไรก็ตามที่อยู่ด้านบน ตัวหารทั่วไปอีกตัวคือ UIButton ที่ด้านล่าง ใน UIViewControllers บางอันฉันมี UIWebView อยู่เหนือ UIButton

ดังนั้น UIImage ข้อความ ฯลฯ UIWebView (บนบาง) UIButton

ล้อมรอบทั้งหมดข้างต้นเป็น UIScrollView

2) สำหรับผู้ที่มี UIWebView การ autoresizingMask จะมีลักษณะดังนี้:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V หน้ากากของ UIButton นั้นไม่ได้มีอะไรที่ยืดหยุ่น

ภายใน -viewDidLoad ของฉันฉันเรียก -repositionSubViews ภายในซึ่งฉันทำสิ่งต่อไปนี้:

หากไม่มี UIWebView ฉันไม่ทำอะไรเลยนอกจากวาง UIButton ที่ฉันวางไว้ที่กึ่งกลาง

หากฉันมี UIWebView ฉันจะพิจารณา * เนื้อหา * ความสูงและตั้งกรอบให้ล้อมเนื้อหาทั้งหมด

UIScrollView *scrollViewInsideWebView = [[webView_ subviews] lastObject];
webViewContentHeight = scrollViewInsideWebView.contentSize.height;
[webView_ setFrame:CGRectMake(webViewOriginX, webViewOriginY,
                          sameWholeViewScrollerWidth, webViewContentHeight)]

เมื่อฉันทำเช่นนั้นฉันจะกด UIButton ลงในโปรแกรมเพื่อให้วางไว้ใต้ UIWebView

ทุกอย่างทำงานได้จนกว่าฉันจะหมุนจากแนวตั้งเป็นแนวนอน

ฉันเรียก -repositionSubViews ภายใน -didRotateFromInterfaceOrientation ของฉัน

ทำไมความสูงของเนื้อหาของ UIWebView ของฉันจึงไม่เปลี่ยนแปลงเมื่อหมุน?

จากแนวตั้งเป็นแนวนอนความกว้างของเนื้อหาควรขยายและความสูงของเนื้อหาควรลดลง มันมองเห็นได้ตามที่ควร แต่ไม่ใช่ตาม NSLog ของฉัน

อย่างไรก็ตามมีหรือไม่มี UIWebView ปุ่มที่ฉันได้พูดคุยเกี่ยวกับการเคลื่อนไหวด้านล่าง TabBar เมื่ออยู่ในโหมดแนวนอน แต่มันจะไม่เลื่อนขึ้นไปให้เห็น ฉันเห็นมันอยู่ด้านหลัง TabBar เมื่อฉันเลื่อน "แรง" แต่แล้วมันก็ "ถอยกลับ" ด้านหลัง TabBar

บรรทัดสุดท้ายนี่คือเหตุผลที่ฉันถามเกี่ยวกับความสูงของ TabBar และ NavigationBar เพราะ TabBar ปลูกเองที่ด้านล่างของ UIView และ NavigationBar ผลัก UIView ลง

ตอนนี้ฉันจะเพิ่มความคิดเห็นหนึ่งหรือสองที่นี่เพราะพวกเขาจะไม่เข้าใจก่อนหน้านี้

เมื่อไม่มี UIWebView ฉันจะทิ้งทุกอย่างตามที่เห็นโดย IB

ด้วย UIWebView ฉันเพิ่มเฟรมของ UIWebView เป็นความสูงของเนื้อหาความสูงและยังปรับความสูงของ UIScrollView โดยรอบที่สูงขึ้นซึ่งล้อมรอบมุมมองย่อยทั้งหมด

คุณก็มีมัน

คำตอบ:


258

ทำอะไรแบบนี้?

    NSLog(@"Navframe Height=%f",
        self.navigationController.navigationBar.frame.size.height);

รุ่นที่รวดเร็วอยู่ที่นี่


UPDATE

iOS 13

เนื่องจากที่statusBarFrameเลิกใช้แล้วiOS13คุณสามารถใช้สิ่งนี้:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

ขอบคุณ. แต่ตอนนี้คุณได้แก้ไขปัญหาดังกล่าวแล้วฉันจะทราบได้อย่างไรว่า NavigationController หรือที่รู้จักในชื่อว่า MoreViewController กำลังแสดงสำหรับแอปแถบแท็บของฉัน

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

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

2
ฉันรู้ว่านี่ไม่ได้ตอบคำถามที่เขาถาม แต่ดูเหมือนว่าเขากำลังมองหาว่าแถบการนำทางซ่อนอยู่หรือไม่ ถ้าเป็นเช่นนั้นเขาจะได้ใช้อย่างเต็มที่ self.navigationController.navigationBarHidden หวังนี้จะช่วยให้คน :)
taylorcressy

2
ใน iOS 7+ คุณอาจต้องพิจารณาแถบสถานะ 20px ขึ้นอยู่กับแอปพลิเคชันของคุณ
Slayter

94

เมื่อใช้ iPhone-X ความสูงของแถบด้านบน (แถบนำทาง + แถบสถานะ) จะเปลี่ยน (เพิ่มขึ้น)

ลองใช้ถ้าคุณต้องการความสูงที่แน่นอนของแถบด้านบน (ทั้งแถบนำทาง + แถบสถานะ):

UPDATE

iOS 13

เนื่องจากที่statusBarFrameเลิกใช้แล้วiOS13คุณสามารถใช้สิ่งนี้:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Objective-C

CGFloat topbarHeight = ([UIApplication sharedApplication].statusBarFrame.size.height +
       (self.navigationController.navigationBar.frame.size.height ?: 0.0));

สวิฟต์ 4

let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
        (self.navigationController?.navigationBar.frame.height ?? 0.0)

เพื่อความสะดวกลองใช้ UIViewController ส่วนขยายนี้

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

สวิฟท์ 3

let topBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height +
(self.navigationController?.navigationBar.frame.height ?? 0.0)


3
Swift 4 คำตอบส่งกลับความสูง 0 สำหรับฉัน
Chewie The Chorkie

61

รุ่นSwift :

let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height

ส่งคืน 44 เสมอวิธีทราบขนาดที่ยุบ (44) หรือขนาดขยาย (ชื่อเรื่องขนาดใหญ่) ??? แน่นอนแบบไดนามิก (ฉันรู้ว่ามันใช้งานได้ขนาดไหน)
มาร์คัส


5

รองรับ iOS 13 และต่ำกว่า:

extension UIViewController {

    var topbarHeight: CGFloat {
        if #available(iOS 13.0, *) {
            return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
                (self.navigationController?.navigationBar.frame.height ?? 0.0)
        } else {
            let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
            return topBarHeight
        }
    }
}

4
UIImage*image = [UIImage imageNamed:@"logo"];

float targetHeight = self.navigationController.navigationBar.frame.size.height;
float logoRatio = image.size.width / image.size.height;
float targetWidth = targetHeight * logoRatio;

UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
// X or Y position can not be manipulated because autolayout handles positions.
//[logoView setFrame:CGRectMake((self.navigationController.navigationBar.frame.size.width - targetWidth) / 2 , (self.navigationController.navigationBar.frame.size.height - targetHeight) / 2 , targetWidth, targetHeight)];
[logoView setFrame:CGRectMake(0, 0, targetWidth, targetHeight)];
self.navigationItem.titleView = logoView;

// How much you pull out the strings and struts, with autolayout, your image will fill the width on navigation bar. So setting only height and content mode is enough/
[logoView setContentMode:UIViewContentModeScaleAspectFit];

/* Autolayout constraints also can not be manipulated since navigation bar has  immutable constraints
self.navigationItem.titleView.translatesAutoresizingMaskIntoConstraints = false;

NSDictionary*metricsArray = @{@"width":[NSNumber numberWithFloat:targetWidth],@"height":[NSNumber numberWithFloat:targetHeight],@"margin":[NSNumber numberWithFloat:20]};
NSDictionary*viewsArray = @{@"titleView":self.navigationItem.titleView};

[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>margin=)-H:[titleView(width)]-(>margin=)-|" options:NSLayoutFormatAlignAllCenterX metrics:metricsArray views:viewsArray]];
[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[titleView(height)]" options:0 metrics:metricsArray views:viewsArray]];

NSLog(@"%f", self.navigationItem.titleView.width );
*/

ดังนั้นสิ่งที่เราต้องการจริงๆคือ

UIImage*image = [UIImage imageNamed:@"logo"];
UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
float targetHeight = self.navigationController.navigationBar.frame.size.height;
[logoView setFrame:CGRectMake(0, 0, 0, targetHeight)];
[logoView setContentMode:UIViewContentModeScaleAspectFit];

self.navigationItem.titleView = logoView;

2

แอปพลิเคชันของฉันมีมุมมองที่ต้องใช้แถบนำทางที่กำหนดเองใน UI สำหรับรูปลักษณ์และความรู้สึก แต่ไม่มีตัวควบคุมการนำทาง และแอพพลิเคชั่นนั้นจำเป็นต้องรองรับ iOS เวอร์ชันก่อน iOS 11 ดังนั้นจึงไม่สามารถใช้คู่มือเลย์เอาต์ปลอดภัยได้และฉันต้องปรับตำแหน่งและความสูงของแถบนำทางโดยทางโปรแกรม

ฉันแนบแถบนำทางไปยังผู้ดูแลโดยตรงโดยข้ามคู่มือเลย์เอาต์พื้นที่ปลอดภัยตามที่กล่าวไว้ข้างต้น และความสูงของแถบสถานะสามารถเรียกคืนจาก UIApplication ได้อย่างง่ายดาย แต่ความสูงของแถบนำทางที่เป็นค่าเริ่มต้นเป็นสิ่งที่เจ็บปวดจริงๆ ...

มันทำให้ฉันเกือบครึ่งคืนมีจำนวนของการค้นหาและการทดสอบจนกว่าฉันจะได้รับคำแนะนำจากโพสต์อื่น (ไม่ได้ทำงานกับฉัน) ว่าคุณสามารถรับความสูงจาก UIView.sizeThatFits () เช่นนี้ :

- (void)viewWillLayoutSubviews {
    self.topBarHeightConstraint.constant = [UIApplication sharedApplication].statusBarFrame.size.height;
    self.navBarHeightConstraint.constant = [self.navigationBar sizeThatFits:CGSizeZero].height;

    [super viewWillLayoutSubviews];    
}

ในที่สุดแถบการนำทางที่สมบูรณ์แบบก็เหมือนกับในตัว!


2

หากคุณต้องการได้navigationBarความสูงเท่านั้นมันง่าย:

extension UIViewController{
   var navigationBarHeight: CGFloat {
       return self.navigationController?.navigationBar.frame.height ?? 0.0
   }
}

อย่างไรก็ตามหากคุณต้องการความสูงของรอยบากด้านบนของ iPhone คุณไม่จำเป็นต้องได้รับnavigationBarความสูงและเพิ่มstatusBarความสูงคุณสามารถเรียกsafeAreaInsetsมันว่าทำไมจึงมีอยู่จริง

self.view.safeAreaInsets.top

1

หลอดไฟเริ่มเข้ามา น่าเสียดายที่ฉันไม่ได้ค้นพบวิธีที่เหมือนกันในการแก้ไขปัญหาดังที่อธิบายไว้ด้านล่าง

ฉันเชื่อว่าปัญหาทั้งหมดของฉันมุ่งเน้นไปที่งานรับอัตโนมัติของฉัน และเหตุผลที่ฉันได้ข้อสรุปว่ามีอาการเดียวกันอยู่โดยมีหรือไม่มี UIWebView และอาการนั้นก็คือทุกอย่างนั้นมีสีพีชสำหรับรูปคน สำหรับแนวนอน UIButton ส่วนใหญ่ที่อยู่ด้านล่างจะปรากฏขึ้นด้านหลัง TabBar

ตัวอย่างเช่นฉันมี UIView หนึ่งรายการจากบนลงล่าง:

UIView - ทั้งชุดสปริง (ตัวพิมพ์ดีฟอลต์) และไม่มี struts

UIScrollView - ถ้าฉันตั้งค่าสปริงทั้งสองและล้างทุกอย่างอื่น (เช่น UIView) UIButton จะบุกรุกวัตถุบนเหนือทันที หากฉันล้างทุกอย่าง UIButton จะใช้ได้ แต่สิ่งที่ซ่อนอยู่ด้านบนสุดด้านหลัง StatusBar การตั้งค่าเฉพาะ strut ด้านบน UIButton จะปรากฏขึ้นด้านหลัง Tab Bar

UILabel และ UIImageติดตั้งในแนวตั้ง - แนวดิ่งบนสุดยืดหยุ่นได้ทุกที่

เพียงเพื่อให้ภาพสมบูรณ์สำหรับคนที่มี UIWebView:

UIWebView - Struts: ด้านบนซ้ายขวาสปริง: ทั้งคู่

UIButton - ไม่ได้ตั้งค่าใด ๆ เช่นยืดหยุ่นได้ทุกที่

แม้ว่าหลอดไฟของฉันจะสลัว แต่ก็มีความหวัง


ติดตั้ง strut ด้านบนและตั้งค่าสปริงสองอันของ UIWebView - แก้ไขปัญหาและขอบคุณมัด ตามความเป็นจริงแล้วปัญหาเดียวที่เหลืออยู่ของฉันคือการออกแบบกราฟิกที่ถูกสาป @ 2X และอื่น ๆ ฉันใช้ GraphicConverter ในวิธีที่ง่ายมากและมันก็ดีสำหรับการออกแบบเว็บเพจได้ดีมาก แต่สิ่งเหล่านี้ 30px, 57px - ฉันจะเข้าสู่ดินแดนที่ไม่มีผู้เช่าสำหรับฉันอย่างน้อย

1

นี่คือจุดเริ่มต้นของการตอบสนองต่อการอัปเดตของคุณ:

ทำไมความสูงของเนื้อหาของ UIWebView ของฉันจึงไม่เปลี่ยนแปลงเมื่อหมุน?

อาจเป็นเพราะการปรับขนาดอัตโนมัติของคุณไม่มีการเปลี่ยนขนาดอัตโนมัติสำหรับทุกทิศทาง

คำแนะนำอื่นก่อนที่ฉันจะกลับมาทำสิ่งนี้คุณสามารถใช้แถบเครื่องมือสำหรับความต้องการของคุณได้ไหม มันง่ายกว่าเล็กน้อยจะอยู่ที่ด้านล่างหมุนอัตโนมัติ / ตำแหน่ง คุณสามารถซ่อน / แสดงมันตามใจชอบเป็นต้นแบบนี้: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

คุณอาจจะมองไปที่ตัวเลือกนั้น แต่ก็ทิ้งมันไป

อีกแนวคิดหนึ่งคือคุณสามารถตรวจจับทิศทางที่คุณกำลังหมุนได้และเพียงวางปุ่มโดยทางโปรแกรมเพื่อปรับสำหรับแถบแท็บ (สามารถใช้รหัสได้)


หลังจากนั้นประมาณ 2 สัปดาห์ในการแก้ปัญหานี้ฉันตัดสินใจว่า "ปัญหา" ทำได้ยากขึ้นโดยการวาง UIButton ด้านล่างของมุมมองย่อย UIWebView ดังนั้นฉันจึงใส่ปุ่มข้างบน ค่อนข้างตรงไปตรงมามันไม่ได้ดู "ถูกต้อง" ในแบบนั้น ... แต่ตอนนี้มันสามารถใช้งานได้เป็นส่วนหนึ่ง ด้านล่างหรือด้านบน UIWebView ได้ตั้งค่า strut ด้านบนและเป็นเพียงแค่สปริงแนวนอน BTW เนื้อหาของความสูงของ UIWebView ที่ไม่เปลี่ยนแปลงด้วยการหมุน

0

ฉันเคยใช้:

let originY: CGFloat = self.navigationController!.navigationBar.frame.maxY

ทำงานได้ดีถ้าคุณต้องการได้ความสูงของแถบนำทางและที่มาของ Y



0

ส่วนขยาย Handy Swift 4 ในกรณีที่เป็นประโยชน์กับคนอื่น ทำงานได้แม้ว่าตัวควบคุมมุมมองปัจจุบันจะไม่แสดงแถบการนำทาง

import UIKit

extension UINavigationController {
  static public func navBarHeight() -> CGFloat {
    let nVc = UINavigationController(rootViewController: UIViewController(nibName: nil, bundle: nil))
    let navBarHeight = nVc.navigationBar.frame.size.height
    return navBarHeight
  }
}

การใช้งาน:

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