Программно получить высоту панели навигации - PullRequest
114 голосов
/ 05 сентября 2011

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

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

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


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

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

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

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

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

UILabel и UIImage следующие по вертикали - набор верхних распорок, гибкие повсюду

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

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

UIButton - ничего не установлено, т. Е. Гибко везде

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


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

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

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

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

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

2) Для тех, у кого есть UIWebView, его маска автоматического изменения размера выглядит следующим образом:

   —
   |
   —

   ^
   |
   |

| - | ← ---- → | - | | | В Маска UIButton не имеет ничего установленного, то есть гибкая везде

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

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

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

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

Как только я это сделаю, я программно нажимаю кнопку UIB вниз, чтобы она оказалась ниже UIWebView.

Все работает, пока я не поверну его из Портрета в Пейзаж.

Я вызываю мои -repositionSubViews в моей -didRotateFromInterfaceOrientation.

Почему высота содержимого моего UIWebView не изменяется при вращении?.

От портрета до пейзажа ширина содержимого должна увеличиваться, а высота содержимого должна уменьшаться. Это происходит визуально, как и должно, но не в соответствии с моим NSLog.

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

В итоге, эта последняя причина, по которой я спросил о высоте TabBar и NavigationBar, потому что TabBar располагается в нижней части UIView, а NavigationBar толкает UIView вниз.

Теперь яЯ собираюсь добавить один или два комментария, потому что они не имели бы смысла раньше.

Без UIWebView я оставляю все как есть у IB.

С UIWebView я увеличиваюframe.height UIWebView к его contentHeight, а также отрегулировать вверх высоту окружающего UIScrollView, который окружает все вложенные представления.

Ну, вот, у вас это есть.

Ответы [ 9 ]

235 голосов
/ 05 сентября 2011

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

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

Быстрая версия расположена здесь

65 голосов
/ 08 февраля 2018

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

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

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)
57 голосов
/ 14 декабря 2014

Swift версия:

let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
6 голосов
/ 30 января 2017

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

let barHeight = self.navigationController?.navigationBar.frame.height ?? 0
4 голосов
/ 08 апреля 2015
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;
1 голос
/ 26 мая 2019

Мое приложение имеет пару представлений, для отображения которых требуется настраиваемая панель навигации в пользовательском интерфейсе, однако без контроллера навигации.Приложение должно поддерживать версию 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];    
}

Наконец, выглядит идеальная панель навигацииточно так же, как встроенный!

1 голос
/ 09 сентября 2011

Вот начало моего ответа на ваше обновление:

Почему высота содержимого моего UIWebView не изменяется при вращении?.

Может ли это бытьпотому что у вашего автоматического изменения размера нет autoresizingMask для всех направлений?

Еще одно предложение, прежде чем я вернусь к этому, не могли бы вы использовать панель инструментов для своих нужд.Это немного проще, всегда будет внизу, автоматическое вращение / положение.Вы можете скрыть / показать его по желанию и т. Д. Примерно так: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

Возможно, вы рассматривали эту опцию, но просто выбросили ее туда.

Еще одна идея: не могли бы вы определить ориентацию, с которой вы вращаетесь, и просто разместить кнопку программно, чтобы настроить панель вкладок.(Это возможно с кодом)

1 голос
/ 07 сентября 2011

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

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

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

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

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

UILabel и UIImage следующий по вертикали - верхняя стойка, гибкая повсюду

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

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

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

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

0 голосов
/ 09 июля 2019

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

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

Прекрасно работает, если вы хотите получить высоту панели навигации и ее происхождение Y.

...