Подтвердить что ты не робот

Изменение iOS меняется после поворота на пейзаж, затем обратно к портрету

Когда мое приложение запускается, 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}}

Затем, когда я поворачиваю симулятор обратно на 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 пикселей были ограблены от ширины и заданы на высоту. Может ли кто-нибудь объяснить это мне и как я мог/должен был кодировать элементы в моем представлении, чтобы учесть это?

Моя раскадровка выглядит следующим образом:

enter image description here

Мое начальное представление: enter image description here

После первого вращения (все еще хорошо) enter image description here

Вращение назад к портрету (все завинчиваются из-за значений границ) enter image description here

4b9b3361

Ответ 1

В willRotateToInterfaceOrientation:duration: вы почти не должны делать макет. Когда система отправит вам willRotateToInterfaceOrientation:duration:, , он не обновил ваш кадр представления до его нового размера. Поэтому, консультируясь с self.view.frame, вы используете кадр для текущей (старой) ориентации, не для рамки для новой (еще не повернутой) ориентации.

Вы также не должны делать макет в viewDidAppear:, потому что к моменту получения viewDidAppear: ваше представление уже находится на экране. Вам нужно сделать макет до вашего представления на экране.

Вам нужно сделать свой макет соответствующим методом. Лучшее место для компоновки - это метод layoutSubviews пользовательского подкласса UIView. Положив его, ваша логика просмотра будет отделена от логики контроллера.

Следующее лучшее место для вашего макета находится в методе viewWillLayoutSubviews или viewDidLayoutSubviews вашего контроллера представлений.

Если вы поместите свой код макета в layoutSubviews, viewWillLayoutSubviews или viewDidLayoutSubviews, система будет автоматически вызывать этот метод до того, как ваше представление появится на экране, а внутри блока анимации авторотации. В обоих случаях он обновит ваш ракурс для правильной ориентации перед отправкой вам сообщения.

Если вам нужно сделать что-то вроде скрытия представления перед запуском анимации авторотации и снова показать его после, вы можете сделать это в willRotateToInterfaceOrientation:duration: и didRotateFromInterfaceOrientation:.

Если вы хотите выполнять специальные анимации только во время авторотации, а не во время первоначального макета представления, вы можете сделать это в willAnimateRotationToInterfaceOrientation:duration:, который вызывается внутри блока анимации авторотации.

Вы можете найти этот ответ полезным: UIViewController возвращает недопустимый фрейм?