Lập trình lấy chiều cao của thanh điều hướng


131

Tôi biết rằng sự hiện diện của bộ điều khiển xem nhiều hơn (thanh điều hướng) sẽ đẩy UIView xuống bằng chiều cao của nó. Tôi cũng biết rằng chiều cao này = 44px. Tôi cũng đã phát hiện ra rằng việc đẩy xuống này duy trì [self.view].frame.origin.y = 0.

Vậy làm cách nào để xác định chiều cao của thanh điều hướng này, ngoài việc chỉ đặt nó thành một hằng số?

Hoặc, phiên bản ngắn hơn, làm cách nào để xác định rằng UIView của tôi đang hiển thị với thanh điều hướng ở trên cùng?


Bóng đèn bắt đầu bật sáng. Thật không may, tôi đã không phát hiện ra một cách thống nhất để khắc phục vấn đề, như được mô tả dưới đây.

Tôi tin rằng toàn bộ vấn đề của tôi tập trung vào nhiệm vụ tự động hóa của tôi. Và lý do tôi đã kết luận rằng có cùng các triệu chứng tồn tại, có hoặc không có UIWebView. Và triệu chứng đó là mọi thứ đều đào hoa cho Portrait. Đối với Cảnh, UIButton dưới cùng bật xuống phía sau TabBar.

Ví dụ: trên một UIView, tôi có, từ trên xuống dưới:

UIView - cả hai lò xo được đặt (trường hợp mặc định) và không có thanh chống

UIScrollView - Nếu tôi đặt hai lò xo và xóa mọi thứ khác (như UIView), thì UIButton xâm nhập vào đối tượng ngay phía trên nó. Nếu tôi xóa tất cả mọi thứ, thì UIButton vẫn ổn, nhưng những thứ ở phía trên cùng ẩn đằng sau StatusBar Chỉ đặt thanh chống trên cùng, UIButton bật xuống phía sau Tab Bar.

UILabel và UIImage tiếp theo theo chiều dọc - bộ thanh chống trên cùng, linh hoạt ở mọi nơi khác

Chỉ cần hoàn thành bức tranh cho một số ít có UIWebView:

UIWebView - Struts: đỉnh, trái, phải Springs: cả hai

UIButton - không có gì được đặt, tức là linh hoạt ở mọi nơi

Mặc dù bóng đèn của tôi mờ, nhưng dường như có hy vọng.


Hãy chịu đựng tôi vì tôi cần nhiều phòng hơn cung cấp cho một bình luận trả lời ngắn.

Cảm ơn vì đã cố gắng hiểu những gì tôi thực sự câu cá ... vì vậy hãy đến đây.

1) Mỗi ​​UIViewContoder (ứng dụng TabBar) có UIImage, một số văn bản và bất cứ thứ gì ở trên đầu. Một mẫu số chung khác là một UIButton ở phía dưới. Trên một số UIViewControllers tôi có UIWebView phía trên UIButton.

Vì vậy, UIImage, văn bản, vv UIWebView (trên MỘT SỐ) UIButton

Bao quanh tất cả những điều trên là một UIScrollView.

2) Đối với những người có UIWebView, autoresizingMask của nó trông giống như:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V Mặt nạ của UIButton không có gì được đặt, tức là linh hoạt ở mọi nơi

Trong -viewDidLoad của tôi, tôi gọi các -reposeitionSubView của mình trong đó tôi thực hiện như sau:

Nếu không có UIWebView, tôi không làm gì ngoài việc căn giữa UIButton mà tôi đã đặt với IB.

Nếu tôi có UIWebView, thì tôi xác định chiều cao * nội dung * của nó và đặt khung của nó để bao quanh toàn bộ nội dung.

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

Khi tôi làm điều đó, sau đó tôi lập trình đẩy UIButton xuống để nó kết thúc được đặt bên dưới UIWebView.

Mọi thứ đều hoạt động, cho đến khi tôi xoay nó từ Chân dung sang Phong cảnh.

Tôi gọi -reposeitionSubViews trong -didRotateFromInterfaceOrientation của tôi.

Tại sao chiều cao nội dung của UIWebView của tôi không thay đổi khi xoay?.

Từ Chân dung đến Phong cảnh, chiều rộng nội dung sẽ mở rộng và chiều cao nội dung sẽ co lại. Nó trực quan như nó cần, nhưng không theo NSLog của tôi.

Dù sao, có hoặc không có UIWebView, nút tôi đã nói về việc di chuyển bên dưới TabBar khi ở chế độ Phong cảnh nhưng nó sẽ không cuộn lên để nhìn thấy. Tôi thấy nó phía sau TabBar khi tôi cuộn "mạnh mẽ", nhưng sau đó nó "rơi lại" phía sau TabBar.

Điểm mấu chốt, đây là lý do tôi đã hỏi về chiều cao của TabBar và NavigationBar vì TabBar tự đặt ở dưới cùng của UIView và NavigationBar đẩy UIView xuống.

Bây giờ, tôi sẽ thêm một hoặc hai nhận xét ở đây vì chúng sẽ không có ý nghĩa sớm hơn.

Không có UIWebView, tôi để mọi thứ như IB thấy.

Với UIWebView, tôi tăng khung hình của UIWebView về nội dung của nó và cũng điều chỉnh chiều cao của UIScrollView xung quanh bao quanh tất cả các chế độ xem phụ.

Được, bạn đã có nó.

Câu trả lời:


258

Làm một cái gì đó như thế này?

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

Phiên bản nhanh chóng được đặt ở đây


CẬP NHẬT

iOS 13

statusBarFrameđã bị phản đối trong iOS13bạn có thể sử dụng điều này:

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

Cảm ơn cảm ơn. NHƯNG, bây giờ bạn đã giải quyết được vấn đề đó, làm thế nào để tôi xác định xem NavigationContoder, hay còn gọi là MoreViewContaptor, đang hiển thị cho ứng dụng thanh tab của tôi.

Tôi không hiểu những gì bạn đang cố nói. Bạn đang cố gắng tìm hiểu xem MoreViewControll có hiển thị không? (Nếu vậy, bạn muốn làm gì?) Và nếu không, bạn có thể làm rõ chính xác ý của bạn là gì không?
Tổng hợp

Tôi đọc lại câu hỏi của bạn và tôi vẫn không hiểu bạn muốn làm gì? Nếu bạn muốn làm gì đó khi khung nhìn xuất hiện, bạn nên chèn mã vào viewDidAppear. Nếu bạn làm rõ một chút, nó sẽ giúp bạn dễ dàng tìm ra những gì bạn muốn làm.
Tổng hợp

2
Tôi biết điều này không giải quyết được câu hỏi mà anh ấy đã hỏi, nhưng có vẻ như anh ấy đang muốn xem điều hướng có bị ẩn hay không. Nếu vậy, ông có thể đã sử dụng self.navigationController.navigationBarHidden Hope đầy đủ này sẽ giúp người :)
taylorcressy

2
Trong iOS 7+, bạn cũng có thể cần xem xét thanh trạng thái 20px tùy thuộc vào ứng dụng của mình
Slayter

94

Với iPhone-X, chiều cao của thanh trên cùng (thanh điều hướng + thanh trạng thái) được thay đổi (tăng).

Hãy thử điều này nếu bạn muốn chiều cao chính xác của thanh trên cùng (cả thanh điều hướng + thanh trạng thái):

CẬP NHẬT

iOS 13

statusBarFrameđã bị phản đối trong iOS13bạn có thể sử dụng điều này:

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

Mục tiêu-C

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

Swift 4

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

Để dễ dàng, hãy thử tiện ích mở rộng UIViewControll này

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

Swift 3

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


3
Câu trả lời Swift 4 trả về chiều cao 0 cho tôi.
Chewie The Chorkie

61

Phiên bản Swift :

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

Luôn trả về 44. Làm thế nào để biết kích thước thu gọn (44) hoặc kích thước mở rộng (tiêu đề lớn) ??? Động, tất nhiên. (Tôi biết những gì nó đo lường)
Markus

6

Bạn đã thử điều này?

let barHeight = self.navigationController?.navigationBar.frame.height ?? 0

5

Hỗ trợ iOS 13 trở xuống:

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 );
*/

Vì vậy, tất cả những gì chúng ta thực sự cần là

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

Ứng dụng của tôi có một vài chế độ xem yêu cầu một thanh điều hướng tùy chỉnh trong giao diện người dùng để xem và cảm nhận, tuy nhiên không có bộ điều khiển điều hướng. Và ứng dụng được yêu cầu hỗ trợ phiên bản iOS trước iOS 11, vì vậy không thể sử dụng hướng dẫn bố cục khu vực an toàn tiện dụng và tôi phải điều chỉnh vị trí và chiều cao của thanh điều hướng theo chương trình.

Tôi đã gắn Thanh điều hướng trực tiếp vào giám sát của nó, bỏ qua hướng dẫn bố trí khu vực an toàn như đã đề cập ở trên. Và chiều cao của thanh trạng thái có thể được lấy từ UIApplication một cách dễ dàng, nhưng chiều cao của thanh điều hướng mặc định thực sự là một ...

Nó đã khiến tôi mất gần nửa đêm, với một số tìm kiếm và thử nghiệm, cho đến khi cuối cùng tôi cũng nhận được gợi ý từ một bài đăng khác (dù không hoạt động với tôi), rằng bạn thực sự có thể có được chiều cao từ UIView.sizeThatFits (), như thế này :

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

    [super viewWillLayoutSubviews];    
}

Cuối cùng, một thanh điều hướng hoàn hảo trông giống hệt như thanh tích hợp!


2

Nếu bạn chỉ muốn có được navigationBarchiều cao, thật đơn giản:

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

Tuy nhiên, nếu bạn cần chiều cao đỉnh cao của iPhone, bạn không cần phải lấy navigationBarchiều cao và thêm statusBarchiều cao, bạn chỉ cần gọi safeAreaInsetsđó là lý do tồn tại.

self.view.safeAreaInsets.top

1

Bóng đèn bắt đầu bật sáng. Thật không may, tôi đã không phát hiện ra một cách thống nhất để khắc phục vấn đề, như được mô tả dưới đây.

Tôi tin rằng toàn bộ vấn đề của tôi tập trung vào nhiệm vụ tự động hóa của tôi. Và lý do tôi đã kết luận rằng có cùng các triệu chứng tồn tại, có hoặc không có UIWebView. Và triệu chứng đó là mọi thứ đều đào hoa cho Portrait. Đối với Cảnh, UIButton dưới cùng bật xuống phía sau TabBar.

Ví dụ: trên một UIView, tôi có, từ trên xuống dưới:

UIView - cả hai lò xo được đặt (trường hợp mặc định) và không có thanh chống

UIScrollView - Nếu tôi đặt hai lò xo và xóa mọi thứ khác (như UIView), thì UIButton xâm nhập vào đối tượng ngay phía trên nó. Nếu tôi xóa tất cả mọi thứ, thì UIButton vẫn ổn, nhưng những thứ ở phía trên cùng ẩn đằng sau StatusBar Chỉ đặt thanh chống trên cùng, UIButton bật xuống phía sau Tab Bar.

UILabel và UIImage tiếp theo theo chiều dọc - bộ thanh chống trên cùng, linh hoạt ở mọi nơi khác

Chỉ cần hoàn thành bức tranh cho một số ít có UIWebView:

UIWebView - Struts: đỉnh, trái, phải Springs: cả hai

UIButton - không có gì được đặt, tức là linh hoạt ở mọi nơi

Mặc dù bóng đèn của tôi mờ, nhưng dường như có hy vọng.


Đặt thanh chống trên cùng và đặt hai lò xo của UIWebView - giải quyết vấn đề và cảm ơn các bó. Trên thực tế, vấn đề duy nhất còn lại của tôi là thiết kế những đồ họa bị nguyền rủa @ 2X, v.v. Tôi sử dụng GraphicConverter theo cách rất đơn giản và nó rất tốt cho thiết kế Trang Web, rất tốt. Nhưng tất cả những thứ 30px, 57px này - ít nhất là tôi sẽ đi vào lãnh thổ không thông minh.

1

Đây là khởi đầu của phản ứng của tôi với bản cập nhật của bạn:

Tại sao chiều cao nội dung của UIWebView của tôi không thay đổi khi xoay?.

Có thể là do tự động thay đổi kích thước của bạn không có autoresizingMask cho tất cả các hướng?

Một đề nghị khác trước khi tôi quay lại vấn đề này, bạn có thể sử dụng thanh công cụ cho nhu cầu của mình không. Nó đơn giản hơn một chút, sẽ luôn ở phía dưới, tự động xoay / vị trí. Bạn có thể ẩn / hiển thị nó theo ý muốn, v.v. Kiểu như thế này: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

Bạn có thể đã xem xét tùy chọn đó, nhưng chỉ cần ném nó ra khỏi đó.

Một ý tưởng khác, bạn có thể phát hiện ra hướng bạn đang xoay từ đâu và chỉ cần đặt nút theo chương trình để điều chỉnh cho thanh tab. (Điều này là có thể với mã)


Sau khoảng 2 tuần để giải quyết vấn đề này, tôi đã quyết định rằng "vấn đề" trở nên khó khăn hơn bằng cách đặt một UIButton DƯỚI chế độ xem phụ UIWebView. Vì vậy, tôi đặt nút TRÊN nó. Thẳng thắn mà nói, nó trông không "đúng" theo cách đó ... nhưng giờ nó hoạt động NGHIÊM TÚC. DƯỚI ĐÂY hoặc TRÊN UIWebView đã đặt thanh chống trên cùng và chỉ là lò xo ngang. BTW, nội dung của nó là UIWebView không thay đổi khi xoay vòng.

0

Tôi đã sử dụng:

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

Hoạt động tuyệt vời nếu bạn muốn có được chiều cao thanh điều hướng VÀ nguồn gốc Y của nó.


0

Swift 5

Nếu bạn muốn o hãy xem xét safeArea:

 let height = navigationController?.navigationBar.frame.maxY  

0

Tiện ích mở rộng Swift 4 tiện dụng, trong trường hợp nó hữu ích cho người khác. Hoạt động ngay cả khi bộ điều khiển xem hiện tại không hiển thị thanh điều hướng.

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

Sử dụng:

UINavigationController.navBarHeight()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.