objective-c - 旋转到横向后 iOS 边界发生变化,然后返回纵向

标签 objective-c ios uiview

当我的应用程序启动时,我的 View 边界的 NSLog 显示如下:

NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));
My view frame: {{0, 0}, {320, 548}}

然后我旋转模拟器并得到以下信息:

NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));
My view frame: {{0, 0}, {320, 548}}

然后当我将模拟器旋转回纵向时,我得到这个:

NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));
My view frame: {{0, 0}, {568, 300}}

我用来调整元素的两种方法是这些,它们还没有完成,因为我目前正在为新的 iphone 修复它们。

-(void) resizeForLandscape
{
    newsLabel = (UILabel *)[self.view viewWithTag:50];
    weatherLabel = (UILabel *)[self.view viewWithTag:51];
    sportsLabel = (UILabel *)[self.view viewWithTag:52];
    entertainmentLabel = (UILabel *)[self.view viewWithTag:53];
    videosLabel = (UILabel *)[self.view viewWithTag:54];
    moreLabel = (UILabel *)[self.view viewWithTag:55];

    NSLog(@"resizeForLandscape called");
    webView.frame = CGRectMake(0, 31, self.view.frame.size.width, self.view.frame.size.height - 75);    
    button.frame = CGRectMake(0, 0, image.size.width -30, image.size.height -15);
    myLabel.frame = CGRectMake(230, 100, 80, 21);
    label.frame = CGRectMake(0, 0, self.view.bounds.size.height + 15, 30);

    NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));
    NSLog(@"my status bar height is %f", [UIApplication sharedApplication].statusBarFrame.size.height);
    NSLog(@"my status bar width is %f", [UIApplication sharedApplication].statusBarFrame.size.width);


    newsLabel.frame = CGRectMake((self.view.bounds.size.height - 346) / 2 + 12, self.view.bounds.size.width - 38, 43, 21);
    weatherLabel.frame = CGRectMake(newsLabel.frame.origin.x + 64, self.view.bounds.size.width - 38, 42, 21);
    sportsLabel.frame = CGRectMake(newsLabel.frame.origin.x + 126, self.view.bounds.size.width - 38, 42, 21);
    entertainmentLabel.frame = CGRectMake(newsLabel.frame.origin.x + 185, self.view.bounds.size.width - 38, 66, 21);
    videosLabel.frame = CGRectMake(newsLabel.frame.origin.x + 269, self.view.bounds.size.width - 38, 42, 21);
    moreLabel.frame = CGRectMake(newsLabel.frame.origin.x + 325, self.view.bounds.size.width - 38, 42, 21);

    spacer1.width = (self.view.bounds.size.height - 346) / 2;
    spacer2.width = 40;
    spacer3.width = 28;
    spacer4.width = 42;
    spacer5.width = 35;
    spacer6.width = 24;
}

-(void) resizeForPortrait
{
    newsLabel = (UILabel *)[self.view viewWithTag:50];
    weatherLabel = (UILabel *)[self.view viewWithTag:51];
    sportsLabel = (UILabel *)[self.view viewWithTag:52];
    entertainmentLabel = (UILabel *)[self.view viewWithTag:53];
    videosLabel = (UILabel *)[self.view viewWithTag:54];
    moreLabel = (UILabel *)[self.view viewWithTag:55];

    NSLog(@"resizeForPortrait called");

    webView.frame = CGRectMake(0, 44, self.view.frame.size.width, self.view.frame.size.height -88);
    button.frame = CGRectMake(0, 0, image.size.width, image.size.height);
    myLabel.frame = CGRectMake(145, 152, 80, 21);
    label.frame = CGRectMake(0, 0, 315, 40);

    NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));

    NSLog(@"my status bar height is %f", [UIApplication sharedApplication].statusBarFrame.size.height);
    NSLog(@"my status bar width is %f", [UIApplication sharedApplication].statusBarFrame.size.width);


    float myWidth = MIN(self.view.bounds.size.height, self.view.bounds.size.width);
    float myHeight = MAX(self.view.bounds.size.height, self.view.bounds.size.width);

    newsLabel.frame = CGRectMake(newsLabel.frame.origin.x, myHeight - 18, 43, 21);
    weatherLabel.frame = CGRectMake(newsLabel.frame.origin.x + 43, myHeight - 18, 42, 21);
    sportsLabel.frame = CGRectMake(newsLabel.frame.origin.x + 97, myHeight - 18, 42, 21);
    entertainmentLabel.frame = CGRectMake(newsLabel.frame.origin.x + 138, myHeight - 18, 66, 21);
    videosLabel.frame = CGRectMake(newsLabel.frame.origin.x + 213, myHeight - 18, 42, 21);
    moreLabel.frame = CGRectMake(newsLabel.frame.origin.x + 258, myHeight - 18, 42, 21);


    spacer1.width = (myWidth - 346) / 2;
    spacer2.width = 20;
    spacer3.width = 18;
    spacer4.width = 25;
    spacer5.width = 28;
    spacer6.width = 14;
}

调用者:

-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        [self resizeForLandscape];
    } else {
        [self resizeForPortrait];
    }
}

- (void) getOrientationandResize
{    
    if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        [self resizeForLandscape];
    } else {
        [self resizeForPortrait];
    }
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self getOrientationandResize];
}

我的脑袋快要爆炸了。不仅 View 颠倒了,而且还从宽度上抢走了 20 个像素并赋予了高度。任何人都可以向我解释这一点,以及我如何/应该如何对我 View 中的元素进行编码来解释它吗?

我的 Storyboard如下:

enter image description here

我的初步看法: enter image description here

第一次轮换后(仍然很好) enter image description here

旋转回纵向(由于边界值,一切都搞砸了) enter image description here

最佳答案

您几乎不应该在 willRotateToInterfaceOrientation:duration: 中进行布局。当系统向您发送 willRotateToInterfaceOrientation:duration: 时,它尚未将您的 View 框架更新为新大小。因此,通过查阅 self.view.frame,您正在使用当前(旧)方向的框架,不是新(尚未旋转-到)方向。

你也不应该在 viewDidAppear: 中进行布局,因为当你收到 viewDidAppear: 时,你的 View 已经在屏幕上了。您需要在 View 显示在屏幕上之前进行布局。

您需要以适当的方式进行布局。进行布局的最佳位置是在自定义 UIView 子类的 layoutSubviews 方法中。将它放在那里可以使您的 View 逻辑与 Controller 逻辑分开。

进行布局的次佳位置是在 View Controller 的 viewWillLayoutSubviewsviewDidLayoutSubviews 方法中。

如果您将布局代码放在 layoutSubviewsviewWillLayoutSubviewsviewDidLayoutSubviews 中,系统将自动调用在您的 View 出现在屏幕上之前以及在自转动画 block 内的那个方法。在这两种情况下,它都会在向您发送消息之前更新您的 View 框架以获得正确的方向。

如果你需要做一些事情,比如在自动旋转动画开始之前隐藏一个 View ,然后再显示它,你可以在 willRotateToInterfaceOrientation:duration:didRotateFromInterfaceOrientation:.

如果你想在自动旋转期间执行特殊动画,而不是在初始 View 布局期间,你可以在 willAnimateRotationToInterfaceOrientation:duration: 中执行此操作,它在内部调用自转的动画 block 。

您可能会发现此答案有帮助:UIViewController returns invalid frame?

关于objective-c - 旋转到横向后 iOS 边界发生变化,然后返回纵向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12412240/

相关文章:

objective-c - LLDB 等同于 gdb 的 future-break?

ios - iOS上相同声音的多个实例

iphone - AFNetworking HTTP POST上传图像即将完成时停止

ios - 当他们向下移动屏幕时从左到右移动 UIView

ios - UIView 响应动画后的方向变化

objective-c - 在横向模式下向 UIScrollView 添加 subview

objective-c - 如何声明具有未确定返回类型的 C 函数?

objective-c - Cocoa - 暂停一个方法

ios - 使用 UIBezierPath 绘制闪烁箭头

objective-c - 符合 Swift 协议(protocol)的具体类类型