旋转到横向后,iOS 边界会发生变化,然后又回到纵向 [英] iOS bounds change after rotating to landscape, then back to portrait

查看:28
本文介绍了旋转到横向后,iOS 边界会发生变化,然后又回到纵向的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When my application launches, an NSLog of my view's bounds shows the following:

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

然后我旋转模拟器并得到以下结果:

I then rotate the simulator and get the following:

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

然后当我将模拟器旋转回肖像时,我得到了这个:

Then when I rotate the simulator back to portait, I get this:

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

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

The two methods I'm using to adjust elements are these, they aren't done yet, as I'm currently in the middle of fixing them for the new 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个像素并给了高度.任何人都可以向我解释这一点,以及我可以/应该如何对我认为的元素进行编码以解释它?

My head is about to explode. Not only are the views reversed, but 20 pixels have been robbed from the width and given to the height. Can anyone explain this to me and how I could/should code the elements in my view to account for it?

我的故事板如下:

我的初步看法:

第一次轮换后(还是不错的)

After first rotation (still good)

旋转回纵向(由于边界值而全部搞砸了)

Rotating back to portrait (all screwed up because of the bounds values)

推荐答案

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

You should pretty much never do layout in willRotateToInterfaceOrientation:duration:. When the system sends you willRotateToInterfaceOrientation:duration:, it has not updated your view's frame to its new size. So by consulting self.view.frame, you're using the frame for the current (old) orientation, not the frame for the new (not-yet-rotated-to) orientation.

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

You should also not do layout in viewDidAppear:, because by the time you receive viewDidAppear:, your view is already on the screen. You need to do layout before your view is on the screen.

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

You need to do your layout in an appropriate method. The best place to do layout is in the layoutSubviews method of a custom UIView subclass. Putting it there keeps your view logic separate from your controller logic.

进行布局的次佳位置是在视图控制器的 viewWillLayoutSubviewsviewDidLayoutSubviews 方法中.

The next-best place to do your layout is in the viewWillLayoutSubviews or viewDidLayoutSubviews method of your view controller.

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

If you put your layout code in layoutSubviews, viewWillLayoutSubviews, or viewDidLayoutSubviews, the system will automatically call that method before your view appears on-screen, and inside the animation block of an autorotation. In both cases, it will update your view's frame for the correct orientation before sending you the message.

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

If you need to do something like hide a view before the autorotation animation starts, and show it again after, you can do that in willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation:.

如果您想在自动旋转期间执行特殊动画,而不是在初始视图布局期间,您可以在 willAnimateRotationToInterfaceOrientation:duration: 中执行此操作,该代码在内部调用自转动画块.

If you want to perform special animations only during an autorotation, and not during initial view layout, you can do that in willAnimateRotationToInterfaceOrientation:duration:, which is called inside the animation block of an autorotation.

您可能会发现这个答案很有帮助:UIViewController 返回无效帧?

You may find this answer helpful: UIViewController returns invalid frame?

这篇关于旋转到横向后,iOS 边界会发生变化,然后又回到纵向的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆