【问题标题】:Where to determine UIView size在哪里确定 UIView 大小
【发布时间】:2009-07-09 10:29:34
【问题描述】:

总结:UIViewController 在初始化视图时应该如何知道其 UIView 实例的大小?

UIView 的专用初始化方法是initWithFrame:(CGRect)frame 方法。这将为新创建的 UIView 设置框架。如果请求视图控制器的视图,则可以从 UIViewController's loadView 方法调用此方法。 UIViewController 的文档说明了子类化和视图大小:

为您的视图创建视图时 层次结构,您应该始终设置 自动调整视图的属性。 当视图控制器显示在 屏幕,它的根视图通常是 调整大小以适应可用空间, 这可以根据 窗口的当前方向和 其他界面元素的存在 比如状态栏。

所以,UIViewController 实例应该设置这些属性。到目前为止一切顺利,UIViewController 到目前为止不必知道它的视图有多大或将有多大。

当请求UIViewController的视图并且视图属性为nil时,调用视图控制器的loadView方法。现在有一个问题,因为UIView需要初始化,但是视图控制器仍然不知道视图应该是什么尺寸。你应该初始化多大的视图?您在代码中的哪个位置确定视图大小?

您可以使用零矩形 (CGRectZero) 初始化视图:

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}

让调用者像这样设置视图框架:

UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);

这会从视图控制器 (viewController.view) 请求视图,从而使用 loadView 方法加载其视图。此 loadView 方法使用 CGRectZero 初始化视图。然后调用者设置它的框架(view.frame = ...)

问题是视图上的 frame 属性设置了两次,如果您的自定义 UIView 在 setFrame 方法中进行一些高级布局(例如放置和调整子视图大小),可能会导致更多的工作。您可以通过为 UIViewController 创建一个专用的初始化方法来防止这种情况,该方法已经向调用者询问了一个 CGRect,您将其存储在一个 ivar 中。在调用 loadView 方法时,您使用此 ivar 创建视图。

去这里的好方法是什么?设置视图的框架两次(使用CGRectZero 初始化,然后设置),或者给UIViewController 一个带有CGRect 的新初始化方法(从而给它一个框架属性)?还是我错过了什么,还有其他可能性吗?

【问题讨论】:

    标签: iphone model-view-controller uiview uiviewcontroller


    【解决方案1】:

    您不必必须使用指定的初始化程序。只需像[[UIView alloc] init] 那样使用init。指定的初始化器必须从子类的初始化器中使用。

    另一方面,将框架设置两次应该不会造成太大的伤害。在setFrame: 中执行大量任务是不寻常的。布局通常在layoutSubviews 中完成,并且只执行一次。

    【讨论】:

    • UIView 的 init 方法实际上调用了零矩形的 initWithFrame
    • 我现在注意到,在对视图应用变换时,会调用 layoutSubviews。考虑到我在视图控制器的 touchesMoved 方法中应用了转换,也不建议在 layoutSubviews 中做很多工作......
    • layoutSubviews 被懒惰地调用(在setNeedsLayout 之后),并且只有一次用于一堆更改。因此,它是执行昂贵的调整大小的最佳场所。
    【解决方案2】:

    我目前正在尝试在从 UIViewController 子类化以创建通用组件后完成同样的事情,并注意到一些非常奇怪的事情:

    UIViewController 有一个“loadView”方法,您可以覆盖它(引用文档)“这是子类应该创建其自定义视图层次结构的地方”。

    所以,我创建了我的视图层次结构,使用默认帧大小合成我的屏幕(因为我可能不知道在调用 loadView 时我应该将内容显示到的帧)。

    但是,我应该在什么情况下正确设置帧大小? Aka : 我的视图控制器什么时候知道它的视图实际大小?

    我是否必须在我的 ViewController 子类中创建一个“setFrame”,创建 viewcontroller 的对象应该调用它?这看起来很奇怪。

    drvdijk : 你的问题有解决方案吗?

    编辑:刚刚在 UIViewController 文档中找到了这个注释: 注意:您不应该使用视图控制器来管理仅填充其窗口的一部分的视图——即仅由应用程序内容矩形定义的区域的一部分。如果您想要一个由多个较小视图组成的界面,请将它们全部嵌入到一个根视图中,并使用您的视图控制器管理该视图。

    所以,UIViewController 主视图似乎总是全屏的。期间。

    这确实给我带来了问题,因为我正在尝试创建一个自定义 UITabBarViewController(以便能够在标签栏中显示自定义图像,而不是蓝色渐变):我的 tabBarViewController 应该将子视图控制器显示到仅窗口...

    【讨论】:

    • italic_You should not use view controllers to manage views that fill ..._italic 这来自 MONO 文档,而不是来自 Apple,并且不正确。
    • 在我引用它时,Apple 似乎更改了文档的那一部分(他们定期更新它)。附带说明一下,前提是您在某些 Mono 文档中找到了该部分(我没有找到):我非常怀疑 Mono 决定自己发明这条规则。他们一定是选择了旧版本的苹果文档并保留了它。
    • 嗯,很久以前,很可能是这样 :-)
    【解决方案3】:

    您可能想要计算可用屏幕空间的界限(这取决于是否存在其他视图,例如导航栏、标签栏和状态栏)。然后,您可以将这些边界用于 loadView 中 [[UIView alloc] initWithFrame:] 中的帧参数。

    如果这是您想要的,那么您可能会发现我在这里的回答很有帮助: Determine the correct size in loadView

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多