32

私はこのコードを実行しています...

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{

                     CGAffineTransform settingsTransform = CGAffineTransformMakeTranslation(self.settingsView.frame.size.width, 0);
                     CGAffineTransform speedTransform = CGAffineTransformMakeTranslation(-self.speedView.frame.size.width, 0);

                     self.settingsView.transform = settingsTransform;
                     self.speedView.transform = speedTransform;

                 } completion:nil];

しかし、それが実行されると、ビューは変換の半分を反対方向にジャンプしてから、正しい方向の半分の位置にスライドします。

アニメーションの長さを5秒に遅くしましたが、最初のジャンプは瞬時に行われ、変換の半分が間違った方向に行われます。

このコードを使用してアニメーション化すると...

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     self.settingsView.transform = CGAffineTransformIdentity;
                     self.speedView.transform = CGAffineTransformIdentity;
                 } completion:nil];

それはまったく同じことをします。

その結果、最初に変換の半分が間違った方向にジャンプするため、最終的な動きは目的の変換の半分になります。

なぜこれが起こっているのか本当に理解できませんか?

何か案は。

::編集::

考えられるあいまいさを解消します。

私は、これらのビューを元の場所に「バウンス」させようとはしていません。私がアニメートしているビューは、画面の端にあるコントロールパネルのようなものです。ユーザーが「移動」を押すと、ビューが邪魔にならないようにスライドします。ユーザーが「停止」を押すと、パネルがスライドしてビューに戻ります。

少なくとも彼らは以前は。自動レイアウト(アプリの他の部分に必要)を有効にしているので、ビューのフレームを変更することはできないので、変換ルートを使用しました。

この効果は、ビューをビューコントローラとボタンに貼り付けてアニメーションを実行することで確認できます。

ありがとう

4

9 に答える 9

71

私はまったく同じ問題を抱えていたので、ここに私が思いついた解決策があります。

    CGAffineTransform transform = CGAffineTransformMake(1, 0, 0, 1, translation.x, translation.y);
    [UIView animateWithDuration:0.25 animations:^{
        _assetImageView.transform = transform;
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
    }];

そこで、[self.view layoutIfNeeded]; を呼び出します。アニメイトブロック内。これがないと、あなたと同じ問題があり、最初に負の距離の移動をジャンプしてから、そこから正しい位置にアニメーション化します。これをView Controllerから呼び出しているので、selfはUIViewControllerのサブクラスです。あなたの場合、「self.view」は存在しないかもしれませんが、理解していただければ幸いです。

于 2012-10-31T01:51:14.910 に答える
16

ここでの解決策はどれもうまくいきませんでした...私のアニメーションは常にスキップしていました。(別のアニメーションの最後にあった場合を除く、ヒント)。

いくつかの詳細:

これを行っていたビューには、一連のスケールと移動が既にスタックにありました。

解決:

最後のアニメーションが設定するはずだった変換を基本的に再適用する非常に短い最初のキーを使用して、キーフレーム アニメーションを実行します。

    UIView.animateKeyframesWithDuration(0.4, delay: 0.0, options: [.CalculationModeCubic], animations: { () -> Void in
        //reset start point
        UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.01, animations: { () -> Void in
            self.element.transform = initialTransform
        })

        UIView.addKeyframeWithRelativeStartTime(0.01, relativeDuration: 0.99, animations: { () -> Void in
            self.element.transform = finalTransform
        })
    }, completion: nil)
于 2016-03-19T00:59:50.930 に答える
8

OK、WWDCビデオをもう一度見たところ、AutoLayoutを使用するときに最初に行う必要があることの1つは、setFrameの呼び出しを削除することであると述べています。

画面が複雑なため、自動レイアウトを完全に削除し、フレームの場所を使用してビューを画面上で移動しています。

ありがとう

于 2012-10-02T11:09:21.613 に答える
1

このアニメーションが発生する前に、settingsView または speedView に既に変換が適用されていますか?

これらのビューの変換が恒等変換 (別名 CGAffineTransformIdentity、別名変換なし) でない場合、それらの .frame プロパティにアクセスできません。

変換が適用されている場合、UIViews のフレーム プロパティは無効です。代わりに「境界」を使用してください。

于 2012-09-21T18:23:06.517 に答える
1

最初のアニメーションの現在の状態から 2 番目のアニメーションを発生させたいので (終了しているかどうかに関係なく) UIViewAnimationOptionLayoutSubviews、2 番目のアニメーションを設定するときにこのオプションを使用することをお勧めします。

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews
                 animations:^{
                     self.settingsView.transform = CGAffineTransformIdentity;
                     self.speedView.transform = CGAffineTransformIdentity;
                 } completion:nil];

シンプルなView Controllerテンプレートを使用してテストに使用したコードのサンプルを次に示します。

myviewcontroller.m:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.animatedView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 160, 80)];
    self.animatedView.backgroundColor = [UIColor yellowColor];

    [UIView animateWithDuration:0.2
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews
                     animations:^{
                         CGAffineTransform settingsTransform = CGAffineTransformMakeTranslation(self.animatedView.frame.size.width, 0);

                         self.animatedView.transform = settingsTransform;

                     }
                     completion:nil];
    self.buttonToTest = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.buttonToTest.frame = CGRectMake(90, 20, 80, 40);
    [self.buttonToTest setTitle:@"Click Me!" forState:UIControlStateNormal];
    [self.buttonToTest addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];

    // set-up view hierarchy
    [self.view addSubview:self.buttonToTest];
    [self.view addSubview: self.animatedView];

}

- (void) buttonClicked
{
    [UIView animateWithDuration:.2
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionLayoutSubviews
                     animations:^{
                         self.animatedView.transform = CGAffineTransformIdentity;

                     }
                     completion:nil];
}
于 2012-09-21T18:47:42.800 に答える
0

layoutIfNeeded について上記の回答を試しましたが、うまくいきませんでした。アニメーション ブロックの外側 (前) に layoutIfNeeded を追加すると、問題が解決しました。

view.layoutIfNeeded()
    
UIView.animate(withDuration: duration, delay: 0, options: .beginFromCurrentState, animations: {
    // Animation here
})
于 2021-03-17T08:33:58.013 に答える