0

実行されたすべての操作を追跡せずに、複数の CGAffineTransform 操作を (アニメーション ブロックで) どのように実行しますか?

平行移動操作では、x、y 座標は使用されませんが、代わりにシフトする値が使用されます。つまり、現在翻訳されている場所、たとえば「場所 2」がわからない場合、「場所 3」に到達するためにどの値をシフトすればよいかをどのように知ることができるでしょうか?

例えば:

UIView のフレームは (0, 0) - 位置 1 にあります。変換を (768, 0) に変換し、-90 度回転 - 位置 2 に設定します。時間が経ち、(768, 1024) に移動したいと思います。さらに -90 度回転 - 位置 3.

2 位から 3 位に移動するために何を変換すればよいかを知るにはどうすればよいですか?

コンテキストでは、次のような iPad ビューを実現しようとしています。

  • 画面全体を占める UIView
  • 上端を占め、UIView の上にある UIToolbar
  • iPad が回転すると、UIView はデバイスにとどまりますが、ツールバーは常に画面の上端に来るように回転します。

CGAffineTransform の移動と回転を使用してツールバーを移動しています。iPadを複数回回転させる場合を除いて、うまく機能します。最初の変換/回転は完璧に機能します。シフトする正しい値がわからないため、次の変換はオフになります。

アップデート:

UIView.transform 構造体で現在の変換 (tx、ty) 値を取得し、それらと新しい場所の違いを使用すると、機能するように見えます。ただし、ビューが回転している場合、これは機能しません。tx と ty の値は、前のローテーションにより反転する可能性があります。私はそれを処理する方法がわかりません。

更新 2:

いくつかの調査を行うと、ポイントの abs 値を取得し、UIView が垂直の場合は x と y を交換することで、tx、ty から元の回転していないポイントを取得できることがわかりました。今、次の一連の変換を正しい順序で正しく適用する方法を考え出しています。それらをどのように連結しても、UIViewは間違った場所に行き着くようです。これは複雑すぎるように思えますが、もっと簡単な方法があるはずです。

4

1 に答える 1

0

答えは、明らかに、変換を追跡しないことです。

したがって、ツールバーを画面上で回転させる方法は、回転と移動の変換を連結しないことです。代わりに、回転変換を作成し、アニメーション ブロックにフレームを設定します。さらに、新しい UIInterfaceOrientation に基づいて、0、-90、-180、-270 のコンパス値に基づいて回転する角度を設定します。また、同じ位置にフレーム サイズ ベースを設定します。

そう:

CGPoint portrait = CGPointMake(0, 0);
CGPoint landscapeLeft = CGPointMake(768 - 44, 0);
CGPoint landscapeRight = CGPointMake(0, 0);
CGPoint upsideDown = CGPointMake(0, 1024 - 44);

CGSize portraitSize = CGSizeMake(768, 44);
CGSize landscapeLeftSize = CGSizeMake(44, 1024);
CGSize landscapeRightSize = CGSizeMake(44, 1024);
CGSize upsideDownSize = CGSizeMake(768, 44);

CGFloat rotation;
CGRect newLocation;
switch(orientation) {
    case UIDeviceOrientationPortrait:
        NSLog(@"Changing to Portrait");
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break;

    case UIDeviceOrientationLandscapeRight:
        NSLog(@"Changing to Landscape Right");
        newLocation.origin = landscapeRight;
        newLocation.size = landscapeRightSize;
        rotation = -90.0;
        break;

    case UIDeviceOrientationLandscapeLeft:
        NSLog(@"Changing to Landscape Left");
        newLocation.origin = landscapeLeft;
        newLocation.size = landscapeLeftSize;
        rotation = -270.0;
        break;

    case UIDeviceOrientationPortraitUpsideDown:
        NSLog(@"Changing to Upside Down");
        newLocation.origin = upsideDown;
        newLocation.size = upsideDownSize;
        rotation = -180.0;
        break;

    default:
        NSLog(@"Unknown orientation: %d", orientation);
        newLocation.origin = portrait;
        newLocation.size = portraitSize;
        rotation = 0.0;
        break; 
}

CGRect frame = newLocation;
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(rotation));

if(lastOrientation) {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:.3];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView setAnimationBeginsFromCurrentState:YES];
}

toolbar.transform = transform;
toolbar.frame = frame;

// Commit the changes
if(lastOrientation) {
    [UIView commitAnimations];
}

lastOrientation = orientation;

これは美しく機能します。ただし、iOS がユーザーに代わって表示する UI 要素の向きが正しくないという予期しない問題があります。つまり、モーダル ウィンドウとポップオーバーはすべて、基礎となる UIView と同じ方向を維持します。その問題は、このすべてを無意味にします。

于 2010-12-10T16:35:57.780 に答える