13

アプリケーションが起動すると、ビューの境界の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}}

私が要素を調整するために使用している2つの方法はこれらですが、私は現在新しい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ピクセルが奪われ、高さに割り当てられます。誰かが私にこれを説明できますか、そしてそれを説明するために私のビューの要素をどのようにコーディングできる/すべきですか?

私のストーリーボードは次のとおりです。

ここに画像の説明を入力してください

私の最初の見解: ここに画像の説明を入力してください

最初の回転後(まだ良い) ここに画像の説明を入力してください

ポートレートに戻る(境界値のためにすべてが台無しになっている) ここに画像の説明を入力してください

4

1 に答える 1

48

でレイアウトを行うことはほとんどありませんwillRotateToInterfaceOrientation:duration:。システムから送信されたときwillRotateToInterfaceOrientation:duration:ビューのフレームは新しいサイズに更新されていません。したがって、を参照すると、新しい(まだ回転されていない)方向のフレームではなくself.view.frame、現在の(古い)方向のフレームを使用していることになります。

viewDidAppear:また、を受け取るviewDidAppear:までに、ビューはすでに画面に表示されているため、でレイアウトを行うべきではありません。ビューが画面に表示される前に、レイアウトを行う必要があります。

適切な方法でレイアウトを行う必要があります。レイアウトを行うのに最適な場所layoutSubviewsは、カスタムUIViewサブクラスのメソッドです。そこに配置すると、ビューロジックがコントローラーロジックから分離されたままになります。

レイアウトを行うための次善の場所は、ViewControllerのviewWillLayoutSubviewsorviewDidLayoutSubviewsメソッドです。

レイアウトコードを、、、layoutSubviewsまたはviewWillLayoutSubviewsに配置すると、ビューが画面に表示される前、および自動回転のアニメーションブロック内viewDidLayoutSubviewsで、システムが自動的にそのメソッドを呼び出します。どちらの場合も、メッセージを送信する前に、ビューのフレームが正しい向きに更新されます。

自動回転アニメーションが開始する前にビューを非表示にし、後で再度表示するなどの操作が必要な場合は、とで行うことができwillRotateToInterfaceOrientation:duration:ますdidRotateFromInterfaceOrientation:

特別なアニメーションを自動回転中にのみ実行し、初期ビューレイアウト中には実行しない場合はwillAnimateRotationToInterfaceOrientation:duration:、自動回転のアニメーションブロック内で呼び出されるで実行できます。

この回答が役立つ場合があります。UIViewControllerが無効なフレームを返しますか?

于 2012-09-13T19:11:30.717 に答える