Почему некоторые из моих UIViews смещаются после навигации?

StackOverflow https://stackoverflow.com/questions/2144502

Вопрос

В некоторых проектах моих приложений или только в некоторых UIViews после pushViewController навигационного контроллера мое новое представление будет смещено за пределы окна на высоту строки состояния.В результате я помещу эту заглушку кода в метод viewDidLoad.

CGRect  frameAt = [self.view frame];
CGRect  statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
frameAt.origin.y += statusBarFrame.size.height;
[self.view setFrame: frameAt];

Для меня не имеет смысла, что это является целью XCode и Interface Builder, поэтому я подозреваю, что делаю что-то фундаментально неправильное с SDK во время проектирования представления.Более того, в тех редких случаях, когда мне не нужно менять свою точку зрения, я действительно не знаю, в чем разница между двумя подходами к проектированию.

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

Кто-нибудь еще сталкивался с этим и знает, что делать, чтобы исправить без такой заглушки кода?

Это было полезно?

Решение

я использовал Пример кода Apple NavBar попытаться воспроизвести эту проблему.

ПриложениеDidFinishLaunching изначально реализовано следующим образом:

[window addSubview:navigationController.view];
[window makeKeyAndVisible];

Если я изменю это на это:

UIViewController *shellController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
[shellController.view addSubview:navigationController.view];
[window addSubview:shellController.view];
[window makeKeyAndVisible];

Потом у меня появляется пробел.

Однако если я сделаю только это:

UIView *shell = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[shell addSubview:navigationController.view];
[window addSubview:shell];
[window makeKeyAndVisible];

Тогда все выглядит нормально.

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

Другие советы

Здесь главное иметь в виду, что контроллер представления сам устанавливает рамку своего представления.Это связано с тем, что объем пространства, доступного для представления, может меняться в течение срока службы приложения, и только контроллер представления знает, как соответствующим образом настроить фрейм представления.Примеры изменения объема пространства включают изменение высоты панели навигации, поворот устройства из книжной ориентации в альбомную, а также может увеличиться высота строки состояния, если пользователь принимает вызов.По этой причине вам не следует самостоятельно изменять рамку представления.

Итак, первое, что вам нужно, это удалить весь код, связанный с изменением рамки представления.

Теперь вам нужно проектировать представления с учетом того, что размер кадра может измениться в любой момент.Это означает правильную настройку свойства автоматического изменения размера каждого подпредставления.Если вы сделаете это, то не будет иметь значения, включите ли вы имитацию навигации и строки состояния или нет;они нужны только для того, чтобы помочь вам увидеть, как будет выглядеть конечный результат в большинстве случаев.

Вы можете установить свойство автоматического изменения размера каждого подпредставления в Интерфейсном Разработчике в Инспекторе размеров (тот, который со значком линейки).В анимации белый прямоугольник представляет корневое представление контроллера представления, красный — выбранное в данный момент подпредставление.Вы заметите, что подпредставление по умолчанию привязано к верхнему левому углу корневого представления.Это нормально, если размер представления никогда не меняется, но мы знаем, что это не так.Если у вас есть подпредставления, которые вы хотите, чтобы они отображались внизу, несмотря ни на что, вам нужно поиграть с диаграммой слева.Это работает следующим образом: если выбрана одна из четырех линий вокруг края, то расстояние между этим краем корневого представления и краем подпредставления фиксируется.Поэтому, если вы хотите, чтобы подпредставление отображалось внизу, вам необходимо убедиться, что выбрана самая нижняя строка, а не верхняя.Две строки посередине влияют на то, изменится ли размер подпредставления при изменении размера корневого представления.Так, например, если у вас есть табличное представление, которое вы хотите занять всю высоту экрана, вам следует убедиться, что выбрана внутренняя вертикальная линия.Это называется моделью стоек и пружин.

Если вы добавляете подпредставления программно, вам необходимо установить свойство autoresizingMask для каждого подпредставления. Вот объяснение.

Надеюсь, это поможет!

текст ссылки

Подобный баг обсуждается здесь.

А для анимации установлено значение НЕТ?Попробуйте установить для него значение «ДА», поскольку это решило аналогичную проблему, с которой я столкнулся.

Ответ Моши был очень полезен, поскольку я наконец понял значение пунктирных/сплошных линий в IB для управления свойствами изменения размера элементов UIView.

Однако настройка этих свойств не решила аналогичную проблему, с которой я столкнулся в одном из своих представлений.Это представление имело статус и верхнюю панель, определенные в IB.Это был немного тяжелый, содержащий UIWebView, который загрузил бы строку HTML внутри viewWillAppear и несколько других элементов интерфейса.

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

Что окончательно решило мои проблемы и оставшиеся волосы, так это добавление строки:

    self.view.frame = [[UIScreen mainScreen] bounds];

в пределах

-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

С тех пор содержимое моего просмотра остается на месте, несмотря на резкие изменения ориентации устройства.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top