问题:我有一个应用程序,其中不同部分使用横向模式(锁定)和纵向模式(锁定)。现在我有一个可行的解决方案,但它似乎不正确,并且有自己的问题。最理想的情况是强制进行方向更改。如果需要,甚至考虑进行视图转换。
应用程序的基本流程:
- HomeView(纵向)(其中有一些子推送视图,也是纵向并锁定在那里)。 - LandscapeView(横向)(其中有5个推送的子视图,也是横向)。
注意:
- HomeView有一个指向LandscapeView的链接。 - LandscapeView可以返回到HomeView。 - 在LandscapeView子视图的末尾,它会返回到HomeView。
基本图像显示了不同视图方向的外观。 (线表示应用程序流程,图像的方向表示每个屏幕应该如何)
目前使用以下实现通过[setLockedToPortait:YES](对于纵向视图)等来调用/设置视图是否处于纵向模式或横向模式。
这会使iOS从设备旋转时查询要使用的界面方向。
现在对于进入LandscapeView的情况,我会在正常视图上方显示一个临时视图,要求使用者将其手机旋转到横向。 (从横向视图返回到HomeView时,也会显示临时视图)
因此,一旦用户旋转了设备,它将触发正确的方向,然后临时视图将隐藏。
如果此时用户将其手机旋转回纵向,则仍将锁定为横向,因此不会触发另一个视图旋转(也不会出现任何临时视图等)。
当前实现代码:
应用程序的基本流程:
- HomeView(纵向)(其中有一些子推送视图,也是纵向并锁定在那里)。 - LandscapeView(横向)(其中有5个推送的子视图,也是横向)。
注意:
- HomeView有一个指向LandscapeView的链接。 - LandscapeView可以返回到HomeView。 - 在LandscapeView子视图的末尾,它会返回到HomeView。
基本图像显示了不同视图方向的外观。 (线表示应用程序流程,图像的方向表示每个屏幕应该如何)
目前使用以下实现通过[setLockedToPortait:YES](对于纵向视图)等来调用/设置视图是否处于纵向模式或横向模式。
这会使iOS从设备旋转时查询要使用的界面方向。
现在对于进入LandscapeView的情况,我会在正常视图上方显示一个临时视图,要求使用者将其手机旋转到横向。 (从横向视图返回到HomeView时,也会显示临时视图)
因此,一旦用户旋转了设备,它将触发正确的方向,然后临时视图将隐藏。
如果此时用户将其手机旋转回纵向,则仍将锁定为横向,因此不会触发另一个视图旋转(也不会出现任何临时视图等)。
当前实现代码:
// ---------------------- NavigationController (subclass of UINavigationController)
@interface NavigationController () {
BOOL isOrientationPortrait;
}
@end
@implementation NavigationController {
UIDeviceOrientation lastAccepted;
UIDeviceOrientation lastKnown;
}
-(void)setLockedToPortait:(BOOL)isLocked {
isOrientationPortrait = isLocked;
}
-(UIDeviceOrientation) getCurrentOrientation {
UIDeviceOrientation orientate = [[UIDevice currentDevice] orientation];
if(orientate == 0) { // needed for simulator
orientate = (UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation;
}
return orientate;
}
// Deprecated in iOS6, still needed for iOS5 support.
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
} else {
if([self isLastKnownLandscape] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
}
}
// iOS6/7 support
- (BOOL)shouldAutorotate
{
// find out the current device orientation
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
} else {
if([self isLastKnownLandscape] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight );
}
}
-(void)setLastAcceptedOrientation:(UIDeviceOrientation)orient {
lastAccepted = orient;
}
-(void)setLastKnownOrientation:(UIDeviceOrientation)orient {
lastKnown = orient;
}
-(BOOL)isLastKnownPortrait {
return UIDeviceOrientationIsPortrait(lastKnown);
}
-(BOOL)isLastKnownLandscape {
return UIDeviceOrientationIsLandscape(lastKnown);
}
-(BOOL)isLastAcceptedPortrait {
return UIDeviceOrientationIsPortrait(lastAccepted);
}
-(BOOL)isLastAcceptedLandscape {
return UIDeviceOrientationIsLandscape(lastAccepted);
}
当前问题:
- 在用户从纵向模式切换到横向模式或从横向模式切换到纵向模式后,需要始终进行设备旋转。
- 如果用户锁定了设备方向,则这根本行不通。
- 当从横向模式返回并且用户已经将其设备旋转到纵向模式(在上一个横向视图中),纵向视图的界面将被锁定为“横向”布局,直到用户重新旋转其设备(所以目前我只是显示叠加层来旋转设备,但它已经旋转了……对用户非常烦人)。目前以上实现存在巨大问题。
希望能够做到:
- 强制更改当前视图的方向。
- 设置一个首选布局,用于在推送/弹出视图之间强制使用。
我在这里和Apple Dev论坛上看过很多其他解决方案,但似乎没有覆盖这个问题,或者这两个视图之间仍然存在方向bug。
感谢任何帮助或指针!没有建议将被忽略:D
-- 编辑:
感谢@leo-natan找到解决方案!
所以,不要试图强制更改视图的方向。只需推送一个新的模态视图。这会强制更改。您仍然需要以上关于管理旋转的方向代码。
因此,现在在我的HomeViewController中是:
LandscapeViewController * viewController = [[[LandscapeViewController ViewController alloc] init] autorelease];
UINib * nib = [UINib nibWithNibName:@"NavigationController" bundle:nil];
NavigationController *navController = [[nib instantiateWithOwner:nil options:nil] objectAtIndex:0];
[navController initWithRootViewController:viewController];
[self presentViewController:navController animated:YES completion:^{
// completion
}];
因此,有必要为此模态视图重新添加一个新的导航控制器。另外请注意,'presentViewController'是推送模态视图的新方式。
实现了这个重载方法来管理视图控制器:
-(id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if(self){
}
return self;
}
注意:以上内容未使用storyboard。可以通过使用storyboard并以相同方式模态显示视图来解决该问题。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
以获取iOS5的相关信息。 - Léo Natan