为啥我的一些 UIView 在导航后会发生变化?

Posted

技术标签:

【中文标题】为啥我的一些 UIView 在导航后会发生变化?【英文标题】:How come some of my UIViews are shifted after navigation?为什么我的一些 UIView 在导航后会发生变化? 【发布时间】:2011-01-09 19:29:28 【问题描述】:

在我的一些应用程序设计中或者只是一些 UIViews 中,在 navigationController 的 pushViewController 之后,我的新视图将被移出窗口状态栏的高度。因此,我会将这段代码存根放在 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 设计我的视图,并进行一些小的自定义。

有没有其他人遇到过这种情况并且知道如果没有这样的代码存根他们会做什么来修复?

【问题讨论】:

另外请注意,我玩过“模拟状态”设置,并且至少有一次,它似乎做出了正确的调整,所以我不必在代码中进行更改。 【参考方案1】:

我已使用Apple's NavBar sample code 尝试重现此问题。

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

然后一切看起来都很正常。

所以我猜如果它是根视图控制器,每个视图控制器都会偏移它的视图。但是导航控制器会覆盖此行为以偏移其视图,无论它是否是根视图控制器。因此,我会说您的差距正在出现,因为您的导航控制器在层次结构中的位置比它应该的要低。

【讨论】:

我认为您正在解决问题。我将检查我的另一个应用程序,它的两个屏幕都有这个问题。我想我可能在那些 UIViewControllers 中添加了一个 UINavigationController。大约 20 分钟后回来...... 谜团解开了!这就对了!!!我真的很感谢你在挖掘这个方面的努力。我学到了一个非常棒的原理,可以将导航栏添加到现有的 UIViewControllers 中。我拥有它们的方式,它们被定义为“在 UIView 层次结构中较低”;这样,当我在代码中将它们添加为 IBOutlet,在 IB 中实例化并将 IB 的导航控制器从我的代码中连接到 IBOutlet 时,我得到了我想要的导航功能并且没有查看工件。此外,我设置框架导致令人不安的“跳跃”迅速回到原位。这是我问题的 110% 正确答案。 我注意到这是在 10 年 3 月回答的。不确定这是否与 ios6 兼容。我遇到了类似的问题,但差距在导航栏下方。这是我的问题:***.com/questions/17790946/… 谢谢。【参考方案2】:

这里要记住的主要事情是视图控制器将设置其视图本身的框架。这是因为视图可用的空间量可能会在应用程序的生命周期内发生变化,并且只有视图控制器知道如何适当地调整视图的框架。空间量变化的示例包括导航栏改变高度、将设备从纵向变为横向以及状态栏在用户接听电话时也会增加高度。因此,您不应自己修改视图的框架。

因此,您需要做的第一件事是删除所有与修改视图框架相关的代码。

现在您需要以框架大小随时可能改变的心态来设计您的视图。这意味着正确设置每个子视图的自动调整大小属性。如果这样做,那么是否打开模拟导航和状态栏都没有关系;它们只是为了帮助您了解大多数情况下的最终结果。

您可以在尺寸检查器(带有标尺图标的那个)中设置界面生成器中每个子视图的自动调整大小属性。在动画中,白框代表视图控制器的根视图,红框代表当前选中的子视图。您会注意到子视图默认锚定在根视图的左上角。如果视图的大小从不改变,这很好,但我们知道这不是真的。如果您有想要出现在底部的子视图,那么您需要使用左侧的图表。它的工作方式是,如果选择了围绕边缘的四条线之一,则根视图的该边缘与子视图的边缘之间的距离是固定的。因此,如果您希望子视图出现在底部,则需要确保选择最底部的行而不是顶部。中间的两行影响根视图改变大小时子视图的大小是否改变。因此,例如,如果您有一个想要占据整个屏幕高度的表格视图,您将确保选择了内部垂直线。这称为支柱和弹簧模型。

如果您以编程方式添加子视图,则需要在每个子视图上设置 autoresizingMask 属性。 Here's an explanation.

希望有帮助!

【讨论】:

嗨 Moshy,我猜你证实了我的想法(让系统管理视图和框架)。不幸的是,随着时间的推移,我的编码中的某些东西会调整一些东西并且框架会发生变化。当我离开然后返回时,它通常是子类视图控制器的视图。我想我的理解是(是)正确的,我真正的问题应该是——我如何确定我做了什么来调整我的层次结构以及我必须修复哪些基本参数/设置。我还(多次)阅读了引用的文档。在我决定这是答案之前,我会做更多的审查。 Moshy,我阅读了 Brian 的问题和回复。他们中的一些人发现他们必须将框架设置为自身的大小——这也是我所做的。这听起来像是方向检测期间的一些大小竞争条件或一些基本的东西。我会检查我的子视图的自动调整大小,如果可行,我会将答案奖励给你。 嗯,如果您发布视图控制器结构可能会有所帮助。文档指定:部署导航界面时,您必须将此视图安装为您正在创建的任何视图层次结构的根。例如,如果您自己部署导航界面,则可以将此视图作为窗口的主子视图。要在标签栏界面中安装导航界面,您需要将导航控制器的视图安装为相应标签的根视图。 好的 .. 在我的一个主要应用程序中,我检查了 100% 的所有视图和使用 addSubviews 添加的视图,并且它们都设置了自动调整大小。我评论了一些深奥的观点。尽管如此,问题仍然存在。我确实发现我已经分配了一个 UINavigationController (尚未“部署”,因此它没有连接到任何东西),如果我将其注释掉,问题就消失了——我的屏幕没有移动。因此,我不能说您的建议回答了我的问题(导航控制器不可见)。 Brian 关于使用 UITabController 管理推送视图的建议也没有。然后我与 IB 合作,我能够让 IB 创建导航控制器 - 在我的程序中设置为 IBOutlet,现在我有一个分配的导航控制器并且视图都是正确的。除非你能给我一个 UINavigationController 的合理理由,否则我不会回答这个问题。【参考方案3】:

我遇到过类似的问题。看看我之前的两个问题:

IPhone - After dismissing Modal View Controller - gap is left at top of page

IPhone - UIView addSubview Gap at top

【讨论】:

嗨,Brian,正如我在我对 Moshy 的 cmets 中提到的(上图),我确实审查了您的问答(我认为我在提出问题之前已经研究过),他们似乎很有希望,但他们确实做到了不解决我的问题。此外,我认为将框架设置为自身的当前设置是错误的解决方案,因为其他东西更可能是错误的。我将留下未解决的问题(我已经回答了我的一个应用程序的问题,但我认为这不是其他应用程序的解决方案)。 好东西——这些回复对我的问题研发很有帮助,并提供了对 SDK 的进一步了解,但是,Moshy 的回答直接解决了我的问题并产生了一些清理副作用。您可能想重新审视您的旧问题,看看这是否是一个更好的解决方案。 - 衷心感谢您的努力。【参考方案4】:

link text

这里讨论了一个类似的错误。

动画也设置为否?尝试将其设置为 YES,因为这解决了我面临的类似问题。

【讨论】:

【参考方案5】:

Moshy 的回答非常有帮助,因为我终于意识到 IB 中的虚线/实线用于控制 UIView 元素的调整大小属性的含义。

但是,调整这些属性并没有解决我在其中一种观点中遇到的类似问题。此视图在 IB 中定义了状态和顶部栏。那是一个略重的, 包含一个 UIWebView,它将在 viewWillAppear 和一些其他界面元素中加载 html 字符串。

在加载视图时,如果用户突然将设备的方向从纵向更改为横向,则视图的所有内容都会向下移动状态栏的高度。即使在切换回纵向方向后,视图控件与其顶部之间产生的间隙仍然存在。

最终解决了我的问题和我剩下的头发的方法是添加以下代码:

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

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

自从我的视图内容在设备方向发生突然变化的情况下保持不变。

【讨论】:

以上是关于为啥我的一些 UIView 在导航后会发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

与嵌入式 UITableView 交互后,为啥我的 UIView 的框架会发生意外变化?

为啥集合视图中的动态集合单元格不显示为给定大小并且在 swift 3 中滚动后会发生变化

为啥 KVO 不能在 UIView 子类上工作?

为啥我的 RoR 应用程序中的 CSS 会根据我是在生产还是开发中运行而发生变化?

为啥UIView动画会改变View frame?

将子 UIView 锁定到 topLayoutGuide