UIViewController在横向模式下呈现时显示不正常。

5

我的应用程序支持纵向和横向两种方向。我正在使用以下代码从位于UITabBarController中的UIViewController模态呈现一个UIViewController:

self.modalViewController = [[ModalViewController alloc] init];

[self presentViewController:self.modalViewController animated:YES completion:^{

}];

ModalViewController是一个控制器,用户只能在横屏模式下看到。它应该能够从LandscapeRight旋转到LandscapeLeft。它的外观如下:

@implementation ModalViewController

#pragma mark - UIViewController - Orientation

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

#pragma mark - NSObject

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor greenColor];
}

#pragma mark - UIViewController - Status Bar

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

@end

控制器从左侧滑出并且在95%的时间内完全覆盖屏幕。但是5%的时间,它从底部滑出并且只覆盖屏幕顶部的一半。
以下是正常工作时的界面:

enter image description here

以下是它运行不良时的外观:

enter image description here

我创建了一个示例项目,可以在这里找到:https://github.com/TitouanVanBelle/Bug 有一个UI测试目标,以帮助重现问题,但它很少起作用。
有人知道为什么会发生这种情况吗?

1
感谢您发布这个问题,我也在寻找解决方案。 - sage444
3个回答

0

这应该是一个评论,但是我声望不够,所以只能回答了。

我觉得我见过类似的错误。

问题的原因可能是在转换过程中发生了方向变化,当调用viewDidLoad时,它仍然是竖屏,但后来变成了横屏,适当的监听器未能正确响应(可能是因为过渡动画状态是“进行中”?)。

修复它的一些想法:

  • 监听方向变化通知,并在当前方向为横屏时显式调用self.view.setNeedsLayout
  • 如果当前方向为竖屏,则在shouldAutorotate中返回false

希望对你有所帮助。


我已经尝试在 shouldAutorotate 中返回 NO,但它并没有解决问题。我将尝试第一个解决方案。谢谢。 - Titouan de Bailleul
即使调用 [self.view setNeedsLayout]; 仍然能够重现问题。 - Titouan de Bailleul

0
你的应用程序支持竖屏、左横屏和右横屏方向。
在ModalViewController.m中更新以下方法 -
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait;
}

你的ModelViewController只支持横向屏幕方向,因此出现了这个问题。

你可以使用UIInterfaceOrientationMaskAllButUpsideDown代替UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait

编辑1

根据你的要求,你可以通过更新ModalViewController.m中的以下代码来强制旋转当前方向。

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor greenColor];

    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

但是,那样用户就可以在横屏和竖屏中显示模态视图控制器,而我不希望如此。我只希望他们能在横屏模式下查看它。 - Titouan de Bailleul
啊啊啊...从你的问题中并不清楚。给我一些时间,我会更新我的答案。 - Akshay Nalawade
正如在此评论中提到的https://dev59.com/318d5IYBdhLWcg3w3FRk#c6qgEYcBWogLw_1bFMR6,使用此API是不安全的,并且可能会在任何iOS版本发布时出现故障。此外,在这里,模态vc从底部滑动而不是从左侧滑动,整个应用程序旋转,这不是我要寻找的。 - Titouan de Bailleul

0

我刚刚尝试了实现相同的功能。从你的问题中我理解到,你只想在横屏模式下显示模型VC。以下是解决方案:

1)将演示样式添加到您的模型VC中,这样它就不会从底部或半屏幕显示。将FirstViewController代码替换为以下内容。

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),
    dispatch_get_main_queue(), ^{
        self.modalViewController = [[ModalViewController alloc] init];
        self.modalViewController.modalPresentationStyle = UIModalPresentationFullScreen;

        NSAssert([NSThread currentThread] == [NSThread mainThread], @"FAIL");

        [self presentViewController:self.modalViewController animated:YES completion:^{}];
    });
}

2) 在 Model VC 中将重写的方法 supportedInterfaceOrientations 更改为以下内容

-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

3) 为了清楚地了解旋转的情况,在 Model VC 上添加一个视图,这样就可以清楚地看到视图是否在旋转。在 Model VC 中添加以下代码:

-(void)viewDidLoad    
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 100)];
    view.backgroundColor = [UIColor redColor];
    [self.view addSubview:view];
}

现在在完成所有这些步骤后,如果您尝试打开应用程序,它将仅以横向模式打开 Model VC,可以旋转为左侧或右侧的横向模式,但纵向模式将被禁用。

这个问题仍然可以通过这个解决方案来复现。 - Titouan de Bailleul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接