Програмно отримати висоту панелі навігації


131

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

Тож як я можу визначити висоту цієї панелі навігації, окрім того, щоб просто встановити її на постійну?

Або, коротша версія, як я можу визначити, що мій UIView відображається з навігаційною панеллю вгорі?


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

Я вважаю, що вся моя проблема зосереджується на моїх автоматизованих масках. І тому я прийшов до висновку, що такі самі симптоми існують, з UIWebView або без нього. І цей симптом полягає в тому, що для портрета все чудово. Для пейзажу найменший UIButton спливає вниз за TabBar.

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

UIView - встановлені як пружини (випадок за замовчуванням), так і ніякі підставки

UIScrollView - Якщо я встановив дві пружини і очистив все інше (як UIView), то UIButton вторгнеться в об'єкт безпосередньо над ним. Якщо я все очищую, то UIButton гаразд, але матеріал у самій верхній частині ховається позаду StatusBar Setting тільки верхньої підпірки, UIButton вискакує за панелі вкладок.

Наступний вертикально UILabel і UIImage - верхня опора, гнучка скрізь

Просто, щоб доповнити зображення для кількох, які мають UIWebView:

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

UIButton - нічого не встановлено, тобто гнучко скрізь

Хоча моя лампочка тьмяна, мабуть, є надія.


Будь ласка, візьміть мене з собою, бо мені було потрібно більше місця, ніж передбачено для короткого коментаря відповіді.

Дякую за те, що спробую зрозуміти, на що я насправді ловлю рибу ... так ось що.

1) Кожен контролер UIViewController (додаток TabBar) має в своєму розпорядженні UIImage, деякий текст та інше. Ще один поширений знаменник - це UIButton внизу. На деяких UIViewControllers я UIWebView над UIButton.

Отже, UIImage, текст тощо. UIWebView (для деяких) UIButton

Оточуючи все вищесказане - це UIScrollView.

2) Для тих, хто має UIWebView, його автоматична маска виглядає так:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V Маска UIButton не має нічого встановленого, тобто гнучка скрізь

У межах -viewDidLoad я називаю my -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, я залишаю все так, як бачить ІБ.

За допомогою UIWebView я збільшую фрейм UIWebView на його contentHeight, а також регулюю вгору висоту навколишнього UIScrollView, що оточує всі підпогляди.

Ну там у вас є.

Відповіді:


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? (Якщо так, то що ви хочете зробити?), А якщо ні, ви могли б уточнити, що саме ви маєте на увазі?
Сума

Я знову прочитав ваше запитання, і я все ще не зрозумів, що ви хочете зробити? Якщо ви хочете щось зробити, коли з'явиться перегляд, вам слід вставити код у viewDidAppear. Якщо трохи уточнити, то було б простіше зрозуміти, що ви хочете зробити.
Сума

2
Я знаю, що це не стосується питання, яке він задав, але, схоже, він шукав, чи навігаційний бар прихований чи ні. Якщо так, він міг би використати self.navigationController.navigationBarHidden Hope повністю це комусь допомагає :)
taylorcressy

2
У iOS 7+ вам може знадобитися також врахувати панель стану 20
пікселів

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

Ціль-С

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

Швидка версія:

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

Завжди повертає 44. Як дізнатися розмір згорнутого (44) або розширеного розміру (великі заголовки) ??? Динамічно, звичайно. (Я знаю, що це вимірює)
Маркус

6

Ви пробували це?

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

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

У моїй програмі є кілька переглядів, для яких потрібен персоналізований панель навігації в інтерфейсі користувача для зовнішнього вигляду, але без контролера навігації. І програма повинна підтримувати версію 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 - встановлені як пружини (випадок за замовчуванням), так і відсутність стійок

UIScrollView - Якщо я встановив дві пружини та очистив все інше (як UIView), то UIButton вторгнеться в об'єкт безпосередньо над ним. Якщо я все очищую, то з UIButton все гаразд, але матеріал у самій верхній частині ховається позаду StatusBar Setting лише верхньої опори, UIButton вискакує за панель вкладок.

Наступний вертикально UILabel і UIImage - верхня опора , гнучка скрізь

Просто, щоб доповнити зображення для кількох, які мають UIWebView:

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

UIButton - нічого не встановлено, тобто гнучко скрізь

Хоча моя лампочка тьмяна, мабуть, є надія.


Встановіть верхню опору і встановіть дві пружини 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. Отже, я кладу кнопку ПРО НАД. Відверто кажучи, це просто не виглядає "правильно" таким чином ... але це зараз працює SORT OF. Внизу або ВНІШЕ UIWebView встановив верхню опору і просто горизонтальну пружину. BTW, його contentHeight 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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.