it-swarm.com.ru

iOS7 - просмотр под строкой состояния - ребраForExtendedLayout не работают

У меня есть проект, который был построен в прошлом году, и он использует XIB, а не раскадровки. XIB не используют Auto Layout, но они используют некоторые Autosizing. У меня есть проблема при запуске с iOS7, в которой все представления скрыты под строкой состояния. Я полностью понимаю, что это новая функция iOS7, в которой этого можно ожидать. Тем не менее, все решения по устранению этого не работают. У меня есть изображение в верхней части представления, которое всегда отображается под строкой состояния, и я не использую навигационные панели или что-то подобное.

Я попытался обновить Y-дельты в XIB (они не влияют на представление), я попытался установить для edgesForExtendedLayout значение UIRectEdgeNone (ничего не делает) и множество других вещей. Каждый раз строка состояния отображается с видом, скрытым под ней, независимо от того, что я делаю ... то есть, если я вручную не перемещаю вниз представление в XIB, чтобы освободить место для строки состояния (но это решение не работает, потому что оно конечно, в iOS6 выглядит не так).

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

self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+20, self.view.frame.size.width, self.view.frame.size.height);

... Не то чтобы я подходил к такому решению, но странно, что оно не сработало (единственный раз, когда я вижу, что это не сработает, это если Auto Layout на месте, чего в данном случае нет).

Это требование дизайна, которое показывает строка состояния, и я просто озадачен, почему я не могу установить представление под строкой состояния для iOS7. Я прочитал каждый пост Stack Overflow на эту тему, а также переходы/руководства Apple. Еще раз повторюсь, я полностью понимаю, как он должен функционировать и каким должно быть ожидаемое решение, но, похоже, ничего из этого не работает для этого конкретного проекта. 

Я опытный разработчик iOS, но этот проект был создан другой командой, поэтому я не знаю, есть ли что-то спрятанное где-то в файлах XIB, plist или коде, которые могут превзойти вышеуказанные настройки. Пожалуйста, дайте мне знать, если есть что-то еще, что можно посмотреть по этому вопросу, или дополнительную информацию, которую я могу предоставить.

Заранее спасибо!

20
svguerin3

Если вы установили значения дельты iOS 6/7 в Интерфейсном Разработчике, не забудьте установить «Вид как» на «iOS 6» в Документе Интерфейсного Разработчика, так как это макет iOS 6, который вы хотите скопировать. Затем дельты будут использоваться только в iOS 7 для отправки содержимого под строку состояния. Если вы оставите «Просмотреть как» в iOS 7 (по умолчанию), вместо дельт будет отображаться iOS 7 в iOS 6.

Однако дельты не помогут вам, если вы переставите или измените размеры представлений программно на основе фрейма вида, так как фрейм не учитывает дельты.

Вместо того, чтобы использовать дельты, лучшее решение, которое я нашел, - это включить автоматическую компоновку на вашей основной XIB, а затем установить ограничение верхнего пространства в представлении top/content, чтобы следовать Руководству по топ-макету. Это руководство было введено в iOS 7 и представляет позицию под строкой состояния. К сожалению, руководство не доступно в Интерфейсном Разработчике, когда раскадровки не используются, но вы можете добавить его программно.

Что я сделал, так это добавил ограничение верхнего пространства к суперпредставлению вместо этого в Интерфейсном Разработчике, и создал выход для этого в коде. Затем в viewDidLoad, если доступен topLayoutGuide (iOS 7+), замените ограничение в этом выпуске версией, использующей вместо этого руководство по верхнему макету.

if ([self respondsToSelector:@selector(topLayoutGuide)]) {
    [self.view removeConstraint:self.containerTopSpaceConstraint];

    self.containerTopSpaceConstraint =
    [NSLayoutConstraint constraintWithItem:self.contentView
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:self.topLayoutGuide
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1
                                  constant:0];

    [self.view addConstraint:self.containerTopSpaceConstraint];

    [self.view setNeedsUpdateConstraints];
    [self.view layoutIfNeeded];
}
17
Kim André Sand

Для справки, приведенное ниже решение сработало, когда я применил его к своим ViewControllers. Тем не менее, это не идеально и немного хакерский. Если это единственный подход, который я могу использовать, пусть будет так.

float systemVersion=[[[UIDevice currentDevice] systemVersion] floatValue];
if(systemVersion>=7.0f)
{
    CGRect tempRect;
    for(UIView *sub in [[self view] subviews])
    {
        tempRect = [sub frame];
        tempRect.Origin.y += 20.0f; //Height of status bar
        [sub setFrame:tempRect];
    }
}
6
svguerin3

Apple заставляет вас использовать autolayout для достижения этой цели. Вам необходимо установить ограничение для "Top Layout Guide" из верхнего подпредставления в вашем представлении.

Смотрите этот документ для примеров:

https://developer.Apple.com/library/ios/qa/qa1797/_index.html

Чтобы сделать это без XIB, вам нужно добавить ограничение программно. Документы Apple дают хороший пример этого, который я суммировал ниже.

Учитывая, что topLayoutGuide является свойством контроллера представления, вы просто используете его в своем словаре привязок переменных. Затем вы устанавливаете ограничение как обычно:

id topGuide = [myViewController topLayoutGuide];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(button, topGuide);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide]-20-[button]" options:0 metrics:nil views:viewsDictionary]; 

Документацию для этого можно найти в справочнике классов UIViewController .

5
petehare

1) Самое простое решение, если вы не против иметь непрозрачную панель навигации:

self.navigationController.navigationBar.translucent = NO;

2) ответ svguerin3 не может работать в общем случае. Например, если одно из ваших подпредставлений использует автоматическое изменение размеров в нижней части своего контейнера, то его новая позиция будет неправильной. И это может выйти за пределы экрана в худшем случае.

3
Aurelien Porte
- (void)viewDidAppear:(BOOL)animated {
        [self.view setFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height)];
// OR
        self.view.transform = CGAffineTransformMakeTranslation(0, 20);
}
2
Mazen Kasser

Если вы используете раскадровку, после настройки верхнего макета вашего представления вы можете снять флажок «Under Opaque Bars» в инспекторе атрибутов.

Storyboard

0
dhin

Вы пытались просмотреть ваши XIB как источники и удалить все строки, содержащие edgeforextendedlayout ??

Нам пришлось удалить эту строку в сценах нашей раскадровки, так как основные виды сцен раскадровки представлены XIB

Для нас происходило то, что каким-то образом в некоторых сценах содержимое XIB для основного вида сцены подавлялось высотой строки состояния и панели навигации.

Удаление этой строки позволило отображать XIB так, как если бы их вершина происходила из той же вершины сцены раскадровки.

К сожалению, мы не имеем ни малейшего представления, что это вызвало, но я видел, как это происходило при изменении порядка содержимого в главном представлении XIB, так что сначала отображался UITextView. Изменение порядка элементов после срабатывания не оказало влияния на удаление этого нежелательного поведения. 

Надеюсь, что это поможет кому-то еще столкнуться с такой проблемой.

0
Alex Zavatone