【问题标题】:Popping UIViewController causes previous UIViewControllers View to change position弹出 UIViewController 会导致之前的 UIViewControllers 视图改变位置
【发布时间】:2015-06-13 12:32:38
【问题描述】:

我有一个 UINavigationController 和一个 UIViewController 设置为它的 rootController,它在它的 UIView 上包含一个背景,使用 navBar 下的一个图像集。然后我将一个新的 UIViewController 推到导航控制器上,当按下后退按钮时,前一个控制器看起来不同。使用可视化调试器,我可以看到 self.view 已完全移至导航栏下方,之前它位于顶部。我不知道为什么会发生这种情况,并且一直在绞尽脑汁

-(void)pushIPhoneMessagingContactsController:(MessageContactsViewController *)contactsController{
    self.selectorView.hidden = YES;
    [self.navigationController pushViewController:contactsController animated:YES];
}

在 RootViewController (iPhoneMessagingNotificationsController)

-(void)viewWillAppear:(BOOL)animated{
    self.selectorView.hidden = NO;
    [[[self navigationItem] leftBarButtonItem] setTintColor:[UIColor blackColor]];
    [[UIApplication sharedApplication]      setStatusBarStyle:UIStatusBarStyleDefault];

    if ([_displayType intValue] == MESSAGES_SHOWING) {
        [self.notificationsViewController.view removeFromSuperview];
        [self.contentView addSubview:_messagesViewController.view];
    } else {
        [self.messagesViewController.view removeFromSuperview];
        [self.contentView addSubview:_notificationsViewController.view];
    }

}

【问题讨论】:

  • 其他一些代码正在影响视图。您是否在过渡期间隐藏或更改了任何会影响顶部布局、导航栏、插图或约束的内容?请显示任何相关代码,例如viewWillAppear。要回答您的问题,我们需要更多详细信息来了解 selectorView 是什么,以及它在视图层次结构中的显示方式/位置。
  • selectorView 是位于导航栏顶部的视图,允许用户在两​​个子视图之间切换。它是在设置 rootViewController 之后添加的,当其他 Controller 被推送时它必须被隐藏。 viewWillAppear 中有一些代码我将添加到问题中。
  • 我已经在 viewWillAppear 中测试了视图框架,它显示视图变为 (0,64,320,504) 而最初是 (0,0,320,504) 所以有些东西正在修改它
  • 为了进一步混淆这个问题,如果我创建一个带有 redBackground 的简单 UIViewController 作为测试并推送它,则不会发生此问题,就好像推送的控制器是导致这个问题,虽然这不应该影响堆栈上其他控制器的布局,但我会想到?

标签: ios uinavigationcontroller


【解决方案1】:

似乎有问题的行在推送的 UIViewController 的 viewWillAppear 方法中

self.navigationController.navigationBar.translucent = YES;

此导航栏在其他地方设置为半透明:

 [self.navigationController.navigationBar setBackgroundImage:[UIImage new]
                                              forBarMetrics:UIBarMetricsDefault];
 self.navigationController.navigationBar.shadowImage = [UIImage new];
 self.navigationController.navigationBar.translucent = YES;

让它再次变成纯色:

 self.navigationController.navigationBar.shadowImage = nil;
 self.navigationController.navigationBar.translucent = NO;

但是这段代码似乎与布局混淆了,所以也许有另一种方法可以在不影响布局的情况下更改 navBar 和 statusBar 的不透明度?

【讨论】:

  • 是的,这破坏了内置行为。如果导航栏不是半透明的,内容将不会被插入,因为在不透明栏下显示视图不再有意义。 Apple 建议您的栏在所有视图控制器中保持一致的外观,所以我会让它们都保持半透明。我会在那里回答这个“问题”。
  • 谢谢你,不过这很有趣,在我看来,一致的外观限制了一些控制器可能需要不同的东西。我们绕过了我们公司的应用商店,所以它没有经过 Apple 审查,所以我想可以侥幸逃脱。
【解决方案2】:

您当前尝试做的是隐藏或显示selectorView,它实际上应该只出现在一个特定的视图控制器中。

这是解决此问题的一种封装方法,它使您的 selectorView 成为根视图控制器的一部分,从而从其他视图控制器中删除连接。他们不再需要知道或隐藏它。

将您的 selectorView 添加到您的 rootViewController 的导航栏 titleView。 (您可以在代码中执行此操作,或将其放入 Storyboard 并为其添加 IBOutlet。)

self.navigationItem.titleView = selectorView;

现在,当您推送另一个视图控制器时,它的标题将替换您的 rootViewController 的 selectorView 标题(视图)。您的其他视图控制器不需要知道关于该视图的任何信息。

总的来说,这是一种很好的设计方法。任何时候你有一个只应该出现在一个视图控制器的导航栏上的控件,你想让它成为那个视图控制器的navigationItem(titleView,或左/右栏按钮项目)的一部分。iOS 将在它出现时显示该控件该视图控制器,并在该视图控制器不再是导航控制器堆栈中的顶部视图控制器时隐藏该控件。

至于 64 像素高度问题,可能与 rootViewController 层次结构中不应该存在的某些复杂性有关。

在 iOS 7/8 中,视图的内容默认显示在半透明导航栏下。 Apple 通过插入视图层次结构的第一个视图,为您免费管理。

从您的代码看来,您正试图“隐藏”或“显示”(未)选定的 viewController 的视图。

每个视图控制器都应该有一个它控制的视图。视图控制器不应试图控制其他视图控制器的 视图,或将其他视图控制器的 视图 添加到自己的视图层次结构中。

这是 Apple 推荐的解决方法。在你的 rootViewController 中使用 containerView。容器视图的全部目的是将视图控制器封装在视图中。当您的 selectorView 更改要显示的视图时,您的容器视图会从一个视图控制器转换到另一个视图控制器。 (如果您不熟悉如何操作,请查看此answer。)

将 containerView 固定到 rootViewController 的视图,以便 Auto Layout 可以为您调整大小。

您的视图层次现在看起来像视图 -> 容器视图,而不是视图 -> 未选定视图控制器的隐藏视图,显示选定视图控制器的视图。 Apple 可以调整第一个视图的插图,并且没有任何东西被错误地偏移(通过导航控件的高度)。

更新:

这个question 谈论scrollViewInsets 以及如何在逐个视图控制器的基础上设置它们。如果您确实有一个视图控制器,并且您不希望它的内容出现在条形下方,请取消选中该框。

但处理此问题的最佳方法是“标准化”您的 UI,因此它不会因视图而异。要么使条始终为半透明,要么不始终为半透明。这使得过渡对用户来说不那么“刺耳”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    相关资源
    最近更新 更多