【问题标题】:View height problems (continued)视图高度问题(续)
【发布时间】:2013-07-26 18:33:43
【问题描述】:

这是我在这里遇到的问题的延续(仍未解决):link

但这可能有助于了解问题所在。 我只创建了一个简单的测试项目(“空应用程序”)并添加了一个带有 XIB 文件的视图控制器(复选框:“选择了用于用户界面的 XIB 文件”)。代码如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"didLoad: %@",NSStringFromCGRect(self.view.bounds));

    // Do any additional setup after loading the view from its nib.
}

-(void) viewDidAppear:(BOOL)animated
{
    NSLog(@"didAppear: %@",NSStringFromCGRect(self.view.bounds));

}

这是输出:

2013-07-26 17:05:28.502 testtest[5926:c07] didLoad: {{0, 0}, {320, 548}}
2013-07-26 17:05:28.506 testtest[5926:c07] didAppear: {{0, 0}, {320, 460}}

他们为什么不一样?

(ps。我在 6.1 模拟器上测试)

【问题讨论】:

  • 您的视图将在实际插入视图层次结构时调整大小。这会受到导航栏、状态栏、工具栏、标签栏等的影响。因此,它在 Interface Builder 中的大小(以及在 viewDidLoad 中加载的大小)在运行时会根据上下文而有所不同。
  • @Mike Weller:这是否意味着我不能依赖 viewDidLoad 中的 self.bounds 等维度?
  • 完全正确。当 viewDidLoad 被调用时,你的视图控制器的视图实际上并没有被插入到视图层次结构中。 viewWillAppear: 是一个更好的地方,更好的是在 UIView 子类中完成所有布局代码。
  • @Mike Weller:想象一下我只有一些自定义 UIView 子类。我想把它放在我的 ViewController 的视图上——我应该把代码放在哪里?

标签: ios objective-c cocoa-touch


【解决方案1】:

当调用viewDidLoad 方法时,您的视图控制器刚刚从您的故事板或 XIB 加载,因此视图尺寸等于您在 XIB 中的尺寸(看起来像 iPhone 5 的高度尺寸) .

稍后,当调用viewDidAppear: 时,视图已经出现在屏幕上,因此它已适当调整大小以实际适合屏幕,因此它的尺寸可能与故事板中的尺寸不同,因此与加载视图时设置的那些。

在您的情况下,您的情节提要或 XIB 文件似乎设置为 iPhone 5 屏幕尺寸(548 = 1136/2 - 状态栏),并且您正在 iPhone 5 之前的模拟器或具有 480x320 点的设备中进行测试屏幕,因此视图的大小被调整为 460 点高以适应屏幕。

【讨论】:

    【解决方案2】:

    这很有道理。

    ViewDidLoad 在第一次访问controller.view 时被延迟调用,所以到那时还没有设置框架。这意味着此时您不能依赖帧/边界大小,因为它只包含一个默认值(尽管在许多情况下它是正确的)。 在ViewDidAppear 中,通常会设置帧,尽管如果您的父控制器正在设置任何动画,您也可以有一个临时帧状态而不是最后一个,但这并不常见,因为按照惯例,当视图是时调用此方法已经显示了。

    例如,如果您从 IB 文件加载视图,您将在 viewDidLoad 中获得的框架是您在 IB 文件中拥有的框架,但您的视图的最终大小可能更小/更大,然后你会在你的viewDidAppear 中得到另一个。

    取而代之的是,您应该创建所有可调整大小的元素(使用 Spring&Struts、AutoLayout 或任何其他类似的替代方法),以便在设置框架时正确显示它们。

    【讨论】:

    • 感谢您的回复,我的 Vcontroller 的视图可以调整大小,您可以从这里看到:postimg.org/image/gx4skl12v
    • 与此无关。视图在 viewDidLoad 上没有正确的框架。就这些。我的建议是调整大小,但不仅是主视图,还有子视图,所以无论视图使用什么大小,元素都会正确显示。您的屏幕截图是关于主视图的,无论自动调整大小属性如何,它通常都会调整大小。
    【解决方案3】:

    ViewController 呈现它的视图时,它通常会缩小它 view 使其框架不会与设备的状态栏重叠。

    所以当你在viewDidLoadNSLog 时,我还没有加载视图,所以ViewController 还没有缩小框架但是在viewDidAppear 中,它已经完成了调整大小。 UIViewController中有一个属性
    wantsFullScreenLayout

    将此属性设置为 YES 会导致视图控制器调整其大小 查看,使其充满整个屏幕,包括下方的区域 状态栏。 (当然,要做到这一点,托管 视图控制器本身必须调整大小以填满整个屏幕, 包括状态栏下方的区域。)您通常会设置 如果您有半透明状态栏,则此属性为 YES 并希望您的视图内容在该视图后面可见。

    【讨论】:

      【解决方案4】:

      据我所知,ViewDidLoad 将在根视图的 RootViewController/XIB 文件或 AppDelegate 中为您的应用程序设置边界。

      如果您在此处定义应用程序边界(不确定其中哪一个),则整个应用程序中的 ViewDidLoad 函数最初将根据该边界设置高度。

      一旦视图被加载并准备好“出现”,就可以请求实际的边界。 因此建议在 ViewWillAppear/ViewDidAppear 方法中请求边界/大小。

      【讨论】:

        【解决方案5】:

        -viewDidLoad 在第一次调用 viewController.view 时被调用。在返回视图之前调用它。这有一个非常重要的含义。为了显示视图或调整视图大小,需要将其添加到窗口或其他视图中。

        这是怎么发生的?它看起来像[window addSubview:viewController.view]

        因此,在将其放入视图层次结构之前,需要完全加载的视图。这对在 -viewDidLoad 中使用时的 self.view 施加了限制。

        1. self.view.superviewself.view.window 将永远是 nil
        2. self.view 的大小尚未适合 self.view.superview

        通过这种理解,您可以看到self.view 在调用-viewDidLoad 时无法知道它的最终大小。


        更新

        如果您需要将自定义布局应用到视图的子视图,您可能需要考虑子类化UIView 并使用-[UIView layoutSubviews]

        除此之外,您是否在使用-viewWillAppear: 而不是-viewDidAppear: 时遇到问题? -viewWillAppear: 在视图显示之前被调用,因此在调整视图大小时不会出现奇怪的视觉效果。

        【讨论】:

        • 这再次意味着我们不能过多地依赖viewDidLoad 中的边界和此类坐标。因此,如果需要一些 UI 安排,是否应该在viwDidAppear 中进行?
        • 想象一下,我只有一个 UIView,它有三个子视图:UIButton、UIButton 和 UITextField - 为什么我必须关心子类化?
        • 或者换一种说法。想象一下,我有一些自定义 UIView 子类,我想将其放置在 ViewController 的视图上。我在哪里写代码?
        猜你喜欢
        • 1970-01-01
        • 2020-01-30
        • 2017-01-16
        • 1970-01-01
        • 2017-07-19
        • 1970-01-01
        • 2020-09-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多