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

Objective c 旋转到横向,然后返回到纵向后,iOS边界发生变化,objective-c,ios,uiview,Objective C,Ios,Uiview,当我的应用程序启动时,我的视图边界的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显示以下内容:

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}, {320, 548}}
NSLog(@"My view frame: %@", NSStringFromCGRect(self.view.bounds));
My view frame: {{0, 0}, {320, 548}}
然后,当我将模拟器旋转回portait时,我得到:

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];
}
我的头快要爆炸了。不仅是视图颠倒了,而且从宽度和高度上都去掉了20个像素。有人能向我解释一下这一点吗?我如何能/应该在我的视图中对元素进行编码来解释这一点

我的故事板如下:

我的初步看法是:

第一次旋转后(仍然良好)

旋转回纵向(由于边界值,所有操作都已拧紧)

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

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

您需要以适当的方法进行布局。进行布局的最佳位置是自定义
UIView
子类的
layoutSubviews
方法。将它放在那里可以使视图逻辑与控制器逻辑分离

进行布局的第二个最佳位置是视图控制器的
viewWillLayoutSubviews
viewdillayoutsubviews
方法

如果将布局代码放入
layoutSubviews
viewWillLayoutSubviews
viewDidLayoutSubviews
,系统将在视图出现在屏幕上之前,在自动旋转的动画块内,自动调用该方法。在这两种情况下,它都会在向您发送消息之前更新视图的框架以获得正确的方向

如果您需要在自动旋转动画开始之前隐藏视图,然后再次显示,则可以在
willRotateToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
中执行此操作

如果只想在自动旋转期间执行特殊动画,而不想在初始视图布局期间执行特殊动画,可以在自动旋转的动画块内调用的
WillAnimateRotationInterfaceOrientation:duration:
中执行


您可能会发现这个答案很有帮助:

我猜您的边界是在设置windows边界之前设置的。最远的20px将是顶部的状态栏。当您从代理旋转时,将调用哪些方法?你用的是IB吗?我想20px是状态栏,但为什么它只在两次旋转后显示?它不应该从一开始就存在吗?另外,更奇怪的是,当我旋转回portait([UIApplication sharedApplication].statusBarFrame.size.height)后打印出状态栏高度时,它说:我的状态栏高度是568.000000。出于好奇,宽度是20px吗?我刚刚测试过,当你旋转它时,它不会改变状态栏的边界,谢谢,我会试试看,然后再打给你!是的,viewDidLayoutSubviews是我的问题的答案。非常好的信息可以指导我正确的做事方式。(+1)