Рядок стану та панель навігації відображаються за межами мого перегляду в iOS 7


435

Нещодавно я завантажив Xcode 5 DP, щоб перевірити свої програми в iOS 7. Перше, що я помітив і підтвердив - це те, що межі мого перегляду не завжди змінюються для врахування рядка стану та панелі навігації.

У viewDidLayoutSubviewsдрукуються межі перегляду:

{{0, 0}, {320, 568}}

Це призводить до того, що мій вміст з’являється під навігаційною панеллю та рядком стану.

Я знаю, що міг би сам пояснити висоту, отримуючи висоту головного екрана, віднімаючи висоту рядка стану та висоту панелі навігації, але це здається зайвою зайвою роботою.

Як я можу виправити це питання?

Оновлення:

Я знайшов рішення для цієї конкретної проблеми. Встановіть для напівпрозорого властивості навігаційної панелі значення НІ:

self.navigationController.navigationBar.translucent = NO;

Це дозволить уникнути обрамлення пода під навігаційною панеллю та рядком стану.

Однак я не знайшов виправлення для випадку, коли потрібно, щоб панель навігації була напівпрозорою. Наприклад, переглядаючи фотографію на весь екран, я хочу, щоб панель навігації була напівпрозорою, а вигляд був обрамлений під нею. Це працює, але коли я перемикаю показ / приховування панелі навігації, я відчував ще більш незначні результати. Перший підпогляд (UIScrollView) змінює своє походження, коли походження змінюється щоразу.


Я також отримую ту саму проблему в xcode 5 DP
Gopesh Gupta,

Повідомте мене, чи отримаєте ви якесь рішення
Гопеш Гупта,

1
Подивіться на панелі навігації властивість кольору відтінку, ви повинні мати можливість змінити цей синій колір на те, що вам потрібно.
beebcon

9
Я іноді ненавиджу оновлення ios, тому що Apple ніколи не давав вам можливості підтримувати ваше додаток назад сумісним.
Bagusflyer

3
Якщо проблема пов'язана з точкою зору відбувається під рядком стану після приховування навігації верхнього контролера бару я хотів би послатися на відповідь на @Stunner stackoverflow.com/a/18976660/235206 як рішення
MikL

Відповіді:


495

Ви можете досягти цього, застосувавши нову властивість, яку називають edgesForExtendedLayoutiOS7 SDK. Додайте наступний код, щоб досягти цього,

if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
        self.edgesForExtendedLayout = UIRectEdgeNone;

Вам потрібно додати вищезазначене у своєму -(void)viewDidLoadметоді.

iOS 7 вносить кілька змін до того, як ви плануєте та налаштовуєте зовнішній вигляд інтерфейсу користувача . Зміни в макеті контролера перегляду, кольорі відтінку та шрифту впливають на всі об’єкти UIKit у вашій програмі. Крім того, вдосконалення API розпізнавання жестів надають вам більш тонкий контроль над взаємодією жестів.

Використання контролерів перегляду

У iOS 7 контролери перегляду використовують компонування на весь екран. У той же час, iOS 7 надає більш детальний контроль над тим, як контролер подання подає свої погляди. Зокрема, концепція повноекранного макета була вдосконалена, щоб дозволити контролеру перегляду вказати макет кожного краю його подання.

В wantsFullScreenLayoutiOS 7. застаріле властивість контролера перегляду застаріло. Якщо ви вказали цей моментwantsFullScreenLayout = NO , контролер уявлення може відображати його вміст в несподіваному місці екрану , коли він працює в прошивці 7.

Щоб настроїти, як контролер перегляду викладає свої подання, UIViewController надає такі властивості:

  • edgeForExtendedLayout

edgesForExtendedLayoutВластивість використовує UIRectEdgeтип, який визначає кожен прямокутника чотирьох ребер, на додаток до не вказавши ні і все. Використовуйте edgesForExtendedLayoutдля вказівки, які краї виду слід розширювати, незалежно від просвічуваності смуги. За замовчуванням значення цього властивості становить UIRectEdgeAll.

  • extensionLayoutIncludesOpaqueBars

Якщо ваш дизайн використовує непрозорі планки, уточніть edgesForExtendedLayout, також встановивши extendedLayoutIncludesOpaqueBarsвластивість на NO . (Значення за замовчуванням extendedLayoutIncludesOpaqueBars- НІ .)

  • автоматичноAdjustsScrollViewInsets

Якщо ви не бажаєте, щоб вставки вмісту перегляду прокрутки автоматично регулювалися, встановіть automaticallyAdjustsScrollViewInsetsзначення НІ . (Типовим значенням automaticallyAdjustsScrollViewInsetsє ТАК .)

  • topLayoutGuide, bottomLayoutGuide

topLayoutGuideІ bottomLayoutGuideвластивості указуют розташування верхніх або нижніх панель країв виду в контролері уявлення. Якщо бари повинні перекривати верхню або нижню частину подання, ви можете скористатися програмою Interface Builder, щоб розташувати подання відносно смуги, створивши обмеження в нижній частині topLayoutGuideабо вгорі нижньої частини LayoutGuide. (Якщо жодна смужка не повинна перекривати подання, нижня частина topLayoutGuideбуде такою ж, як вершина подання, а верхня bottomLayoutGuide- така сама, як і нижня частина перегляду.) Обидва властивості створюються ліниво, коли запитуються.

Будь ласка, зверніться, яблучний док


2
Він не буде компілюватися під iOS6. Я думаю, що це має бути написано як
виконавський селектор

8
Так, саме тому я включив перевірку селектора з умовою, якщо ([self responseToSelector: @selector (edgeForExtendedLayout)])
Nandha

19
Це не спрацює, якщо у мене немає навігаційної панелі. У такому випадку мій погляд поширюється за рядком статусу ..
Van Du Tran

4
У мене така ж проблема, як і @VanDuTran. edgeForExtendedLayout не допомагає, якщо навігаційна панель прихована.
fishinear

6
це працює, але ... більше немає ефекту напівпрозорості ... як ми можемо зберегти просвічуючий ефект також ...
Dipu Rajak

110

Вам не доведеться обчислювати, як далеко перенести все вниз, для цього є властивість. У програмі Interface Builder виділіть контролер перегляду та перейдіть до інспектора атрибутів. Тут ви побачите кілька прапорців поруч із словами "Розширити краї". Як бачите, на першому знімку екрана за замовчуванням вибрано вміст, який відображатиметься під верхньою та нижньою смугами, але не під непрозорими смужками, тому налаштування стилю смуги не просвічує для вас.

Як ви можете дещо побачити на першому скріншоті, під панеллю навігації ховаються два елементи інтерфейсу. (Я включив провідні кадри в ІБ, щоб проілюструвати це) Ці елементи, UIButton та UISegmentedControl мають походження "y", встановлене на нуль, а контролер перегляду встановлений таким чином, щоб дозволити вміст нижче верхнього рядка.

введіть тут опис зображення

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

введіть тут опис зображення

Це також може бути здійснено програмно за допомогою використання -[UIViewController edgesForExtendedLayout]. Ось посилання на посилання на клас для edgeForExtendedLayout та для UIRectEdge

[self setEdgesForExtendedLayout:UIRectEdgeNone];

15
Як зробити те саме для просто перегляду в .xib?
бобіки

2
Я додав одну мітку на перегляд, і я дотримувався вашої інструкції, але це для мене не працює
RMRAHUL

5
@bobics Відповідь на питання XIB - "Ви не можете". Не через ІБ все одно. Подайте радар і сподівайтеся, що Apple врешті-решт вирішить його.
пам’ятки

Дякую @ 0x7fffffff, Це була лише така інформація, яку я шукав і була дуже корисною.
campo

33

Я створив свій погляд програмно, і це закінчилося для мене:

- (void) viewDidLayoutSubviews {
    // only works for iOS 7+
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;

        // snaps the view under the status bar (iOS 6 style)
        viewBounds.origin.y = topBarOffset * -1;

        // shrink the bounds of your view to compensate for the offset
        viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1);
        self.view.bounds = viewBounds;
    }
}

Джерело (у розділі topLayoutGuide внизу сторінки.39).


Нарешті знайшов відповідь, яка насправді для цього працює. Гарна робота!
StuartM

1
Щоб вирішити проблему, згідно з якою подання контролера перегляду відображається під панеллю стану, коли навігаційна панель прихована, це код, який знімає подання під рядком стану.
MiKL

Примітка. Це витісне нижню частину зору з екрана.
пам’ятки

1
Крім того, якщо ви не будуєте лише для iOS7, наведений вище код призведе до помилки - topLayoutGuideце лише iOS7.
пам’ятки

1
Також зауважте, що коли ваш головний вигляд є UITableView, viewDidLayoutSubviews буде викликано під час кожного прокрутки. Ваш UITableView буде зменшено до тих пір, поки його висота не буде 15 пікселів Додайте прапор, щоб запустити цей код лише один раз. ;)
Томас Йоганнесмайер

30

Рішення Swift 3 / Swift 4, яке також працює з файлами NIB / XIB в iOS 10+:

override func viewDidLoad() {
    super.viewDidLoad()

    edgesForExtendedLayout = []
}

Це те, що мені допомогло ... Так просто. Дякую :-)
Ернан Арбер

Дякую, що це справді корисно
Мухаммед Ахмед Байг

Це найкраще рішення для 10.x IMO Swift 3+
шокавели

10

Якщо ви хочете, щоб у перегляду була напівпрозора смуга навігації (що дуже приємно), ви повинні встановити contentInset або подібне.

Ось як я це роблю:

// Check if we are running on ios7
if([[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."][0] intValue] >= 7) {
      CGRect statusBarViewRect = [[UIApplication sharedApplication] statusBarFrame];
      float heightPadding = statusBarViewRect.size.height+self.navigationController.navigationBar.frame.size.height;

      myContentView.contentInset = UIEdgeInsetsMake(heightPadding, 0.0, 0.0, 0.0);
}

3
чому ви не можете безпосередньо порівняти це з 7.0
Leena

1
lol Я розумію: перевірка проти конкретної версії з незначними додаваннями є менш надійною. Але ви перевіряєте, чи значення ВІДПОВІДНЕЕ або дорівнює тому порівнянню з 7,0, тут було б чудово;)
EeKay

1
@leena - це функції в 7.x і пізніших версіях - тому я перевіряю, чи версія 7 або більше, і пропускаю незначні зміни в чеку.
Магнус

2
У мене виникла проблема з моєю таблицею ViewView, відображеною за моєю вкладкою. Що змусило останній рядок моєї таблиці ніколи не прокручуватися над вкладкою. Я виправив це так: myTableView.contentInset = UIEdgeInsetsMake (0, 0,0, TabbarHeight, 0)
Джеймс Лоренстін

contentInsetє властивістю UIScrollView. Що робити, якщо мій основний погляд не є підкласом UIScrollView. Тоді як я можу виправити проблему перекриття?
Pwner

9

edgesForExtendedLayoutробить фокус для iOS 7. Однак, якщо ви будуєте додаток через iOS 7 SDK і розгортаєте його в iOS 6, панель навігації виглядає напівпрозорою, а види переходять під неї. Отже, щоб виправити це як для iOS 7, так і для iOS 6, зробіть це:

self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

9

Додайте рядок до файлу списку програм, назвіть його "Перегляд зовнішнього вигляду на основі контролера" та встановіть його на " НІ" .


7

Найпростіший трюк - відкрити файл NIB і виконати ці два прості дії:

  1. Просто перемкніть це та встановіть його на той, який вам більше подобається:

Введіть тут опис зображення

  1. Виберіть ті UIView / UIIMageView / ..., які потрібно перемістити вниз. У моєму випадку лише логотип перекривався, я встановив дельту +15; (АБО -15, якщо ви вибрали iOS 7 на кроці 1)

Введіть тут опис зображення

І результат :

До цього Після


6
Це працює, але це виглядає як важке для підтримки рішення. Найкраще було б просто виправити проблему, а не латати її.
NLemay

найкраще це робити програмно для всіх
підпрезентацій

5

Швидке рішення:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.edgesForExtendedLayout = UIRectEdge.None
}

4
Тепер це краї ForForxxEndedLayout = []
Леон,

1
Оскільки це публічна відповідь, ми не повинні забувати зателефонувати:super.viewWillAppear(animated)
prodos

4

Я хотів би розгорнути відповідь Штунера і додати відповідь if заяву, щоб перевірити, чи це iOS-7, тому що, коли я тестував його на iOS 6, моя програма зірветься.

Додаток буде додавати:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

Тому я б запропонував додати цей метод у свій MyViewControler.mфайл:

- (void) viewDidLayoutSubviews {
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect viewBounds = self.view.bounds;
        CGFloat topBarOffset = self.topLayoutGuide.length;
        viewBounds.origin.y = topBarOffset * -1;
        self.view.bounds = viewBounds;
    }
}


3

У мене є сценарій, коли я використовую BannerViewController, написаний компанією Apple, для показу своїх оголошень і ScrollViewController, вбудований у BannerViewController.

Щоб панель навігації не приховувала мій вміст, мені довелося внести дві зміни.

1) Змініть BannerViewController.m

- (void)viewDidLoad
{
   [super viewDidLoad];
   float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
   if (systemVersion >= 7.0) {
      self.edgesForExtendedLayout = UIRectEdgeNone;
   }
}

2) Змініть мій ScrollViewContoller

- (void)viewDidLoad
{
    [super viewDidLoad];
    float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (systemVersion >= 7.0) {
        self.edgesForExtendedLayout = UIRectEdgeBottom;
    }
}

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


2

просто встановіть наступний код у поданому вигляді.

  if ([[[UIDevice currentDevice] systemVersion] floatValue]<= 7) {
self.edgesForExtendedLayout = UIRectEdgeNone;
 }

Це єдине, що працювало в моїх обставинах.
goobliata


2

Swift 4.2 - Xcode 10.0 - iOS 12.0:

if #available(iOS 11.0, *) {} else {
  self.edgesForExtendedLayout = []
  self.navigationController?.view.backgroundColor = .white
}

1

Для мене найпростішим рішенням є додати два ключі до списку

введіть тут опис зображення


+1, у мене був "Рядок стану спочатку приховано" = ТАК, але додаючи "Перегляд вигляду рядка стану на основі контролера" = НІ, я позбувся рядка стану.
Jonas Byström

1

Додайте ключ "Переглянути зовнішній вигляд рядка стану на основі контролера" зі спадного списку як рядок у info.plist. Щось на зразок цього:

Введіть тут опис зображення


Цікаво це допомогло в моїх проектах cocos2d.Я перемикаю цю опцію, я бачу, що верхня панель стану повністю зникла або з'явилася.
Курсат Туркай

1

У мене була та сама проблема з моїм додатком iPad (armv7, armv7s, amr64) лише за допомогою представлення іншого UIViewController, і після їх відхилення переходить до навігаційного рядка під рядком стану ... Я витрачаю багато часу, щоб знайти рішення для цього. Я використовую розкадровку і в InterfaceBuilder для UIViewController, що робить жахливим я встановлюю презентацію з FullScreen -> Поточний контекст, і це вирішує цю проблему. Він працює в моєму додатку лише для iPad => iOS8.0 (тестування з iOS8.1), а для iPad із iOS 7.1 не працює !!див. скріншот


У моєму випадку моя основна думка перекривала мій tabBar, і я не мав ідеї, чому. Виявляється, Розширені краї> Під нижньою смугою було перевірено. Це було важко помітити, тому що фон мого додатка був білим, і він створював лише деяку непрозорість мого вкладки. Дякую!
Ісус Родрігес

0

Крок для приховування рядка стану в iOS 7:

1.Перейти до файлу info.plist програми.

2.І встановіть, перегляньте зовнішній вигляд рядка стану на основі контролера: Булевий НІ

Сподіваюсь, я вирішив питання рядка стану .....


0

У моєму випадку перервано loadView ()
цей код: self.edgesForExtendedLayout = UIRectEdgeNone

але після видалення loadView () все працювало нормально

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.