#iphone #landscape #storyboard #xcode4.2 #device-orientation
#iPhone #пейзаж #раскадровка #xcode4.2 #ориентация устройства
Вопрос:
Я обновился до xCode 4.2, и это новая функция раскадровки. Однако не удалось найти способ поддерживать как портретную, так и альбомную ориентацию.
Конечно, я сделал это программно, с 2 видами, один для портрета и один для ландшафта, как в старые времена, и:
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
Но я искал способ каким-то образом сделать это автоматически. Я имею в виду, что теперь это xCode 4.2, я ожидал от него большего. Спасибо всем.
==================================
ВРЕМЕННОЕ РЕШЕНИЕ:
Я представлю здесь временное решение. Я говорю, что это временно, потому что я все еще жду, когда ребята из Apple сделают что-то действительно разумное по этому поводу.
Я создал другой файл .storyboard под названием «MainStoryboard_iPhone_Landscape» и внедрил в него контроллеры ландшафтного представления. На самом деле, это точно так же, как обычный (портретный) .storyboard, но все экраны находятся в альбомном режиме.
Итак, я извлеку ViewController из альбомной раскадровки, и когда произойдет поворот, просто измените self.view на представление нового ViewController.
1. Генерировать уведомления при изменении ориентации:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
2. Ищите уведомления:
[[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceOrientationDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
// We must add a delay here, otherwise we'll swap in the new view
// too quickly and we'll get an animation glitch
[self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];
}];
3. Реализовать обновление Landscapeview
- (void)updateLandscapeView {
//> isShowingLandscapeView is declared in AppDelegate, so you won't need to declare it in each ViewController
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) amp;amp; !appDelegate().isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone_Landscape" bundle:[NSBundle mainBundle]];
MDBLogin *loginVC_landscape = [storyboard instantiateViewControllerWithIdentifier:@"MDBLogin"];
appDelegate().isShowingLandscapeView = YES;
[UIView transitionWithView:loginVC_landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
//> Setup self.view to be the landscape view
self.view = loginVC_landscape.view;
} completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) amp;amp; appDelegate().isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:[NSBundle mainBundle]];
MDBLogin *loginVC = [storyboard instantiateViewControllerWithIdentifier:@"MDBLogin"];
appDelegate().isShowingLandscapeView = NO;
[UIView transitionWithView:loginVC.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
//> Setup self.view to be now the previous portrait view
self.view = loginVC.view;
} completion:NULL];
}}
Удачи всем.
P.S: Я приму ответ Ad Taylor, потому что после долгого ожидания и поиска решения я закончил реализацию чего-то, вдохновленного его ответом. Спасибо Тейлору.
Комментарии:
1. self.view = NewView; приведет ли к сбою приложение на iOS 6
Ответ №1:
Это старый вопрос, но я прочитал это ранее в тот же день, а затем мне пришлось потратить немало времени на разработку лучшего решения. Я пришел к этому решению, взломав пример альтернативного просмотра Apple. В основном это предоставление модального представления для альбомной ориентации.
#pragma mark Rotation view control
- (void)orientationChanged:(NSNotification *)notification
{
// We must add a delay here, otherwise we'll swap in the new view
// too quickly and we'll get an animation glitch
[self performSelector:@selector(updateLandscapeView) withObject:nil afterDelay:0];
}
- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) amp;amp; !self.isShowingLandscapeView)
{
[self performSegueWithIdentifier: @"toLandscape" sender: self];
self.isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait amp;amp; self.isShowingLandscapeView)
{
[self dismissModalViewControllerAnimated:YES];
self.isShowingLandscapeView = NO;
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Комментарии:
1. Я принял ваш ответ, потому что это вдохновило меня на решение моей проблемы. Однако вместо того, чтобы представлять / отклонять modalViewController, я просто перехожу к другому представлению. Спасибо Тейлору.
Ответ №2:
Обычно вам не следует думать об отдельных представлениях для разных ориентаций, если они не сильно отличаются (чего, возможно, не должно быть). Вместо этого вы должны полагаться на маски авторазработки, чтобы размещать как можно больше содержимого вашего просмотра на основе базовых ограничений при изменении рамки супервизора. Это позволит подвидам соответствующим образом реагировать на изменение фрейма их супервидения, часто в результате изменения ориентации интерфейса.
Чтобы ответить на ваш вопрос более прямо, нет, у Xcode нет возможности предположить или узнать, какие представления вы хотите использовать для определенной ориентации интерфейса, поскольку это никогда не было целью UIKit
архитектуры view.
Вот дополнительная информация об авторазмерных масках: Автоматическая обработка изменений макета с использованием правил авторазмеризации.
Комментарии:
1. Спасибо за ответ. Но до версии 4.2 у нас была возможность добавлять 2 вида в один ViewController и настраивать их отдельно, книжный и альбомный. Я вижу, что теперь мы МОЖЕМ добавить второе представление в ViewController, но мы не можем его видеть. Нажмите на нее, чтобы настроить, и вы не сможете ее увидеть. И есть некоторые случаи (у меня их много), когда авторазмер действительно не помогает. Что мы должны делать тогда?
2. А, теперь я понимаю, что ты имеешь в виду. Похоже, это ошибка с раскадровками (или, возможно, желаемое поведение). Я заметил то же самое, и это может быть проблемой. Я предлагаю сообщить об ошибке в Apple.
Ответ №3:
В XCode версии 4.2.1 при использовании раскадровок вы можете изменять ориентацию только контроллера представления, а не самого представления, поэтому, если вы вставили туда другое представление, вы не сможете изменить его ориентацию, даже если вы сможете правильно просматривать представление.
Таким образом, предыдущий способ создания двух представлений, по-видимому, не будет работать при использовании раскадровок (при использовании наконечников, где ориентация представления может изменяться для отдельных представлений).
Комментарии:
1. Хм, и как бы вы справились с этой проблемой, когда вам нужны портретная и альбомная ориентации, но когда авторотации недостаточно? У меня все еще нет выбора. Я хочу, чтобы контроллер просмотра главного меню, например, располагал меню в альбомном режиме иначе, чем в портретном режиме. Есть идеи, пожалуйста?