Почему некоторые из моих UIViews сдвигаются после навигации? - PullRequest
10 голосов
/ 27 января 2010

В некоторых моих проектах приложений или только для некоторых UIViews, после pushViewController navigationController, мой новый вид будет смещен за пределы окна на высоту строки состояния. В результате я помещу эту заглушку кода в метод 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, с небольшими изменениями.

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

Ответы [ 5 ]

16 голосов
/ 05 марта 2010

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

applicationDidFinishLaunching изначально реализовано так:

[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];

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

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

2 голосов
/ 04 марта 2010

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

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

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

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

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

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

1 голос
/ 05 марта 2010

Я столкнулся с похожими проблемами. Проверьте мои два предыдущих вопроса:

IPhone - После увольнения контроллера Modal View - пробел остается вверху страницы

IPhone - UIView addSubview Gap вверху

0 голосов
/ 01 февраля 2012

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

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

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

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

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

в пределах

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

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

0 голосов
/ 29 июня 2010

текст ссылки

Подобная ошибка обсуждается здесь.

Также анимация установлена ​​на НЕТ?Попробуйте установить его в YES, поскольку это решило похожую проблему, с которой я столкнулся.

...