Программно получить высоту панели навигации

131

Я знаю, что наличие контроллера more view (панель навигации) смещает UIView по высоте. Я также знаю, что эта высота = 44 пикселя. Я также обнаружил, что это нажатие поддерживает [self.view].frame.origin.y = 0.

Итак, как мне определить высоту этой панели навигации, кроме как просто установить ее на константу?

Или, в более короткой версии, как определить, что мой UIView отображается с панелью навигации вверху?


Лампочка начала гореть. К сожалению, я не нашел единого способа исправить проблему, как описано ниже.

Я считаю, что вся моя проблема связана с автоизменением размеров маски. И причина, по которой я пришел к выводу, в том, что существуют те же симптомы, с UIWebView или без него. И этот симптом в том, что для портрета все идеально. Для ландшафта самый нижний элемент UIButton появляется за TabBar.

Например, на одном UIView у меня сверху вниз:

UIView - обе пружины установлены (случай по умолчанию) и без подкосов

UIScrollView - если я установил две пружины и очистил все остальное (например, UIView), то UIButton вторгнется в объект, расположенный непосредственно над ним. Если я все очищу, тогда UIButton в порядке, но материал на самом верху скрывается за StatusBar. Настройка только верхней стойки, UIButton появляется за панелью вкладок.

UILabel и UIImage next по вертикали - набор верхних стоек, гибкость везде

Чтобы завершить картину для тех немногих, у кого есть UIWebView:

UIWebView - Стойки: сверху, слева, справа Пружины: обе

UIButton - ничего не задано, т.е. гибкий везде

Хотя моя лампочка тусклая, похоже, есть надежда.


Пожалуйста, терпите меня, потому что мне нужно больше места, чем предусмотрено для короткого комментария.

Спасибо за попытку понять, что я на самом деле ловлю ... итак.

1) Каждый UIViewController (приложение TabBar) имеет UIImage, некоторый текст и все, что находится сверху. Еще один общий знаменатель - UIButton внизу. На некоторых UIViewControllers у меня есть UIWebView над UIButton.

Итак, UIImage, текст и т. Д. UIWebView (НЕКОТОРЫЕ) UIButton

Все вышеперечисленное окружает UIScrollView.

2) Для тех, у кого есть UIWebView, его autoresizingMask выглядит так:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V Маска UIButton ничего не настроена, т.е. гибкая везде

В моем -viewDidLoad я вызываю свой -repositionSubViews, в котором я делаю следующее:

Если UIWebView отсутствует, я ничего не делаю, кроме центрирования UIButton, который я разместил с IB.

Если у меня есть UIWebView, я определяю его * content * Height и устанавливаю его фрейм так, чтобы он заключал все содержимое.

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 я увеличиваю frame.height UIWebView до его contentHeight, а также увеличиваю высоту окружающего UIScrollView, который окружает все под-представления.

Ну вот и все.

Krunal
источник

Ответы:

258

Сделать что-нибудь подобное?

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

Быстрая версия находится здесь


ОБНОВИТЬ

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? (Если да, то что вы хотите сделать?), А если нет, не могли бы вы пояснить, что именно вы имеете в виду?
Sum
Я снова прочитал ваш вопрос, но все еще не понял, что вы хотите сделать? Если вы хотите что-то сделать при появлении представления, вам следует вставить код в viewDidAppear. Если вы немного проясните, вам будет легче понять, что вы хотите делать.
Sum
2
Я знаю, что это не касается вопроса, который он задал, но, похоже, он искал, была ли панель навигации скрыта или нет. Если так, он мог бы использовать self.navigationController.navigationBarHidden Hope полностью, это кому-то поможет :)
taylorcressy
2
В iOS 7+ вам может потребоваться также рассмотреть строку состояния в 20 пикселей в зависимости от вашего приложения
Slayter
94

В iPhone-X высота верхней панели (панель навигации + строка состояния) изменена (увеличена).

Попробуйте это, если вам нужна точная высота верхней панели (как панель навигации, так и строка состояния):

ОБНОВИТЬ

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

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

Swift 3

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

Krunal
источник
3
Ответ Swift 4 возвращает мне высоту 0.
Chewie The Chorkie
61

Быстрая версия:

let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
Король-Мастер
источник
Всегда возвращает 44. Как узнать размер свернутого (44) или развернутого (большие заголовки) ??? Конечно, динамично. (Я знаю, что он измеряет)
Маркус
6

Вы пробовали это?

let barHeight = self.navigationController?.navigationBar.frame.height ?? 0
Keaz
источник
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;
Ironik Sütlaç
источник
2

В моем приложении есть несколько представлений, для которых требуется настраиваемая панель навигации в пользовательском интерфейсе для внешнего вида, но без контроллера навигации. И приложение должно поддерживать версию 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
Mojtaba Al Moussawi
источник
1

Лампочка начала гореть. К сожалению, я не нашел единого способа исправить проблему, как описано ниже.

Я считаю, что вся моя проблема связана с автоизменением размеров маски. И причина, по которой я пришел к выводу, в том, что существуют те же симптомы, с UIWebView или без него. И этот симптом в том, что для портрета все идеально. Для ландшафта самый нижний элемент UIButton появляется за TabBar.

Например, на одном UIView у меня сверху вниз:

UIView - обе пружины установлены (случай по умолчанию) и без подкосов

UIScrollView - если я установил две пружины и очистил все остальное (например, UIView), то UIButton вторгнется в объект, расположенный непосредственно над ним. Если я все очищу, тогда UIButton в порядке, но материал на самом верху скрывается за StatusBar. Настройка только верхней стойки, UIButton появляется за панелью вкладок.

UILabel и UIImage next по вертикали - набор верхних стоек , гибкость везде

Чтобы завершить картину для тех немногих, у кого есть UIWebView:

UIWebView - Стойки: сверху, слева, справа Пружины: обе

UIButton - ничего не задано, т.е. гибкий везде

Хотя моя лампочка тусклая, похоже, есть надежда.


источник
Установить верхнюю распорку и установить две пружины UIWebView - проблема решена и спасибо кучу. На самом деле, у меня единственная оставшаяся проблема - это создать графику cursed @ 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 установил верхнюю стойку и только горизонтальную пружину. Кстати, это contentHeight UIWebView, который не меняется при вращении.
0

Я использовал:

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

Отлично работает, если вы хотите получить высоту панели навигации И ее начало Y.

user3332228
источник
0

Swift 5

Если вы хотите рассмотреть также безопасную область:

 let height = navigationController?.navigationBar.frame.maxY  
Кивиа Мартинс Брито
источник
0

Удобное расширение 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()
CodenameDuchess
источник