为什么我的一些 UIView 在导航后会发生移动?

发布于 2024-08-19 06:37:48 字数 554 浏览 5 评论 0原文

在我的一些应用程序设计中或者只是一些 UIViews 中,在导航控制器的 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 来设计我的视图,并进行一些小的自定义。

还有其他人遇到过这个问题并且知道在没有这样的代码存根的情况下他们要做什么吗?

In some of my application designs or for just some UIViews, following a navigationController's pushViewController, my new view will be shifted off the window by the height of the status bar. As a result, I will put this code stub in the viewDidLoad method.

CGRect  frameAt = [self.view frame];
CGRect  statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
frameAt.origin.y += statusBarFrame.size.height;
[self.view setFrame: frameAt];

It does not make sense to me that this is the intention of XCode and Interface Builder, so I suspect that I am doing something fundamentally wrong with the SDK during my view design. Furthermore, on the rare occasion that I don't have to shift my view, I really don't know what the difference in the two design approaches.

Note also, that most of the time I try to design my views using IB, with some minor customization.

Does anyone else run into this and know what they do to fix without such a code stub?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

甜点 2024-08-26 06:37:48

我已经使用 Apple 的 NavBar 示例代码 来尝试重现此内容问题。

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

那么一切看起来都很正常。

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

I've used Apple's NavBar sample code to try and reproduce this problem.

the applicationDidFinishLaunching is originally implemented like this:

[window addSubview:navigationController.view];
[window makeKeyAndVisible];

If I change it to this:

UIViewController *shellController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
[shellController.view addSubview:navigationController.view];
[window addSubview:shellController.view];
[window makeKeyAndVisible];

Then I get the gap appearing.

However if I only do this:

UIView *shell = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[shell addSubview:navigationController.view];
[window addSubview:shell];
[window makeKeyAndVisible];

Then everything looks normal.

So I guess every view controller will offset its view if its the root view controller. But the navigation controller overrides this behaviour to offset its view regardless of whether it's the root view controller. Therefore I would say your gap is appearing because you've got a navigation controller somewhere lower in the hierarchy than it's supposed to be.

烛影斜 2024-08-26 06:37:48

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

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

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

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

如果您以编程方式添加子视图,则需要在每个子视图上设置 autoresizingMask 属性。 这是一个解释

希望有帮助!

The main thing to keep in mind here is that a view controller will set the frame of its view itself. This is because the amount of space available to the view may change during the lifetime of the app, and only the view controller knows how to adjust the view's frame appropriately. Examples of when the amount of space changes include the navigation bar changing height, turning the device from portrait to landscape and the status bar can also increase in height if the user is taking a call. Because of this you should not modify the view's frame yourself.

So, the first thing you need to is is remove all code related to modifiying the view's frame.

Now you need to design your views with the mindset that the frame size could change at any moment. This means setting the autoresizing property of each subview properly. If you do this, then it won't matter if you turn on the simulated navigation and status bars or not; they're just there to help you see what the final result will look like in most cases.

You can set the autoresizing property of each subview in Interface Builder in the Size Inspector (the one with the ruler icon). In the animation, the white box represents the root view of the view controller, the red box represents the currently selected subview. You'll notice that the subview is anchored to the top-left corner of the root view by default. This is fine if the size of the view never changes, but we know that not to be true. If you have subviews that you want to appear at the bottom no-matter-what, then you need to play with the diagram to the left. The way it works is if one of the four lines around the edge is selected, then the distance between that edge of the root view and the edge of the subview is fixed. So if you want a subview to appear at the bottom, you need to make sure the bottom-most line is selected and not the top. The two lines in the middle affect whether the size of the subview changes when the root view change size. So, for example, if you had a table view that you wanted to occupy the entire height of the screen, you would make sure the inner vertical line was selected. This is called the struts and springs model.

If you are adding subviews programatically you need to set the autoresizingMask property on each subview. Here's an explanation.

Hope that helps!

谜兔 2024-08-26 06:37:48

链接文本

此处讨论了类似的错误。

动画也设置为NO吗?尝试将其设置为“是”,因为这解决了我面临的类似问题。

link text

A similar bug is discussed here.

Also is animation set to NO? Try setting it to YES as this solved a similar problem I was facing.

入画浅相思 2024-08-26 06:37:48

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

然而,调整这些属性并没有解决我的观点之一所面临的类似问题。该视图具有在 IB 中定义的状态和顶部栏。本来是有点重的,
包含一个 UIWebView,它将在 viewWillAppear 和一些其他界面元素中加载 HTML 字符串。

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

最终解决我的问题和我剩余的头发的是添加一行:

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

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

自从我的视图内容保持在适当的位置,尽管设备方向突然发生变化

Moshy's answer was very helpful as I finally realized the meaning of the dotted/solid lines in IB for controlling the resize properties of UIView elements.

However, adjusting those properties did not address a similar problem I faced with one of my views. This view had a status and top bar defined in IB. It was a slightly heavy one,
containing a UIWebView that would load a HTML string within viewWillAppear and a few other interface elements.

While loading the view, if the user suddenly changed the orientation of the device from portrait to landscape, all contents of the view would shift downwards by the height of the status bar. The resulting gap between the view controls and its top would remain even after switching back to portrait orientation.

What finally solved my issues, and my remaining hair, was adding the line:

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

within

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

Ever since my view contents are held in place despite abrupt device orientation changes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文