在 iOS Superviews 中强制布局位置和大小

Posted

技术标签:

【中文标题】在 iOS Superviews 中强制布局位置和大小【英文标题】:Forcing a layout position and size in iOS Superviews 【发布时间】:2012-05-03 12:42:08 【问题描述】:

我有一个大问题,我真的希望你能在这里帮助我......我现在很迷茫:(

我有一个使用 MainWindow.xib 运行的项目。在我的应用程序委托文件中,我检查设备的方向并加载一个适当的 NIB 文件,该文件具有基于方向的不同布局(子视图)。这是检查方向的代码:

-(void)checkTheOrientation

    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) 
    
        viewController = [[[MyViewController alloc] initWithNibName:@"MyWideViewController" bundle:nil] autorelease];
        NSLog(@"Landscape = MyWideViewController");
     
    else if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown)
       
        viewController = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
        NSLog(@"Portrait = MyViewController"); 
    

这可以按预期工作,并且在横向或纵向中我正在加载正确的视图。纵向视图加载完美,但横向视图加载时左侧有一个厚黑边,好像它的 x 和 y 位置没有分别设置为 0 和 0。

这是纵向视图:http://uploads.socialcode.biz/2f25352B0e3x3z2t2z21 这是有 bug 的横向视图:http://uploads.socialcode.biz/1G2k3T012d1z0Y1U2q1k

在 MyViewController.m 文件中,我有一个粗略的修复来正确调整大小以避免左侧出现这个大黑条。这是代码:

- (void) performLayout 
    // Ensure the main view is properly placed
    NSInteger MaxSizeHeight, MaxSizeWidth;

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
    
        MaxSizeHeight = 1024;
        MaxSizeWidth  = 768;
    
    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) 
        CGRect mainViewFrame = [[self view] frame];
        float width = mainViewFrame.size.width;
        mainViewFrame.size.width = mainViewFrame.size.height;
        mainViewFrame.size.height = width;
        mainViewFrame.origin.x = 0;
        mainViewFrame.origin.y = 0;
        [[self view] setFrame:mainViewFrame];
     else 
        CGRect mainViewFrame = [[self view] frame];
        mainViewFrame.origin.x = MaxSizeWidth - mainViewFrame.size.width;
        mainViewFrame.origin.y = MaxSizeHeight - mainViewFrame.size.height;
        [[self view] setFrame:mainViewFrame];
    

    // Ensure the content view is properly placed
    CGRect contentFrame = [mainContentView frame];
    if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) 
    
        contentFrame.size.width = MaxSizeHeight;
        contentFrame.size.height = MaxSizeWidth;
    
    contentFrame.origin.x = 0;
    contentFrame.origin.y = 44;
    [mainContentView setFrame:contentFrame];

    // Ensure the content subviews are properly placed
    contentFrame.origin.y = 0;
    for (UIView *contentView in [mainContentView subviews]) 
        [contentView setFrame:contentFrame];
    

这种方法的问题在于,这只是一个非常糟糕的 hack,实际上并没有解决我的问题。当它在 Landscape 中加载时,它现在会调整子视图的大小并将其定位为 1024x768,0,0,但我通过其他 NIB 加载的任何其他子视图都有同样的问题。

我真正想知道的是,我到底如何才能将横向主超级视图设置为 1024x768 位置 0 和 0,而不必尝试将其组合在一起并继续执行 performLayout 选择器?目前这有很多不一致之处,因为黑客实际上并没有正确设置超级视图的大小,而只是我在超级视图之上加载的子视图。

我认为像这样的简单修复可能会解决 superview 问题,但可惜它没有: window.frame = CGRectMake(0, 0, 1024, 768);

我只希望我的主超级视图在加载时正确放置和调整大小,然后超级视图加载到正确的位置。请问你能帮我吗???

【问题讨论】:

一点评论(与答案无关):这不是正确的方法,更好的方法是从 xib 文件中设置正确的行为。我使用了相同的方法,但在大型应用程序中遇到了可怕的问题。 @MarcoPace 我以前从未遇到过 XIB 文件的问题,但无论我在 IB 中做什么,都没有真正改变我的布局。我只是担心也许 MainWindow.xib (不能从肖像模式更改)是问题的根本原因。你有什么建议我可以试试? 【参考方案1】:

首先,UIView 有一个名为-layoutSubviews 的方法,您可以覆盖该方法以随意放置子视图。它会在第一次加载视图时被调用,如果你曾经向它发送-setNeedsLayout 消息,则会在绘制之前再次调用它。

其次,您应该能够在 .xib 或故事板文件中正确设置这些位置。在其 .xib 文件中选择您的主视图并检查其在大小检查器中的位置。此外,确保在属性检查器中将视图设置为横向。如果一切都正确,那么还有其他事情正在发生。为了简化问题,在 Xcode 中创建一个新项目,除了横向的空视图之外什么都没有。我刚做了一个,没有位置问题。这就是您在实际应用中想要的,因此请弄清楚您的实际应用中发生了什么来影响新示例应用中没有发生的视图位置。

【讨论】:

迦勒,感谢您的评论。我现在可以正确执行 layoutSubviews(使用 NSLog 验证),但左侧仍然有奇怪的黑色空间。这是我的代码: 这是我的代码(抱歉,当我按 Enter 时,Stack Overflow 会继续发布我的 cmets)...pastie.org/3855031

以上是关于在 iOS Superviews 中强制布局位置和大小的主要内容,如果未能解决你的问题,请参考以下文章

iOS 故事板 - 自动布局不会调整子视图的大小和位置

在 LongPressEnded 之后迅速从 SuperViews 中删除视图

修复 D3 强制定向布局中的节点位置

ios 7 - 强制视图布局翻转到 RTL 而无需更改语言

如何在 iOS 应用程序中强制“始终”访问位置

d3js 在地图上强制布局