0

制約に変換しようとしているアニメーションがいくつかあります。その背後にある考え方は、エラーが発生したときにログイン プロンプトがバウンスするというものです。

私のアプローチは、ビュー コントローラーのすべてがメイン ビュー内にあるバウンス ビュー内にあるということです。

バウンスビューは、中央揃えの制約と先頭のスペースの制約を使用してメイン ビューに結び付けられます。設計時にレイアウトを明確にするために、先頭のスペースと上部のスペースの制約もあります。ただし、これらは単なるプレースホルダーであり、実行時に同じ高さ/幅の制約に置き換えられます。

メイン ビューに関連付けられているその他の制約はありません。

さて、いくつかの詳細…</p>

これらの制約を使用してバウンスを定義します。

enum {animationDone, bounceStart, bounceLeft, bounceRight, bounceReturn};
static const NSTimeInterval BounceDuration = 20.0;
static const int NumberOfBounces = 3;
static const CGFloat BounceDistance = 16.0f;

(通常、20 秒の遅延ははるかに短くなります。これが機能していないことを証明するために、遅延を増やしました。)

追加の実行時制約は次のように設定されます。

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:_bounceView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:_bounceView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
}

次のコードでアニメーションを開始します。

_animateCount = NumberOfBounces;
_animateStage = bounceStart;
[self animationStep];

実際のコードは非常に単純です。

- (void)animationStep {
    CGFloat bounceTo = 0;
    BOOL half = NO;
    switch (_animateStage) {
        case bounceStart:
            _animateStage = bounceLeft;
            bounceTo = -BounceDistance;
            half = YES;
            break;
        case bounceLeft:
            _animateStage = bounceRight;
            bounceTo = BounceDistance;
            break;
        case bounceRight:
            if ( --_animateCount > 0 ) {
                _animateStage = bounceLeft;
                bounceTo = -BounceDistance;
            } else {
                _animateStage = bounceReturn;
                bounceTo = 0;
            }
            break;
        case bounceReturn:
            half = YES;
            _animateStage = animationDone;
            break;
    }

    BOOL finishedAnimation = ( ( _animateStage == animationDone ) || ( self.view == nil ) );

    if ( !finishedAnimation ) {
        [_bounceView layoutIfNeeded];
        _centerX.constant = bounceTo;
        [_bounceView setNeedsUpdateConstraints];

        NSTimeInterval duration = half ? BounceDuration / 2.0f : BounceDuration;
        [UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            NSLog(@"Bouncing to %f over %f seconds.", bounceTo, duration);
            [_bounceView layoutIfNeeded];
        } completion:^(BOOL finished) {
            [self animationStep];
        }];
    }
}

ただし、これはすべて即座に完了します。

2013-10-29 10:59:43.852 App[9151:907] Bouncing to -16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.864 App[9151:907] Bouncing to 16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.865 App[9151:907] Bouncing to -16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.866 App[9151:907] Bouncing to 16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.866 App[9151:907] Bouncing to -16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.867 App[9151:907] Bouncing to 16.000000 over 20.000000 seconds.
2013-10-29 10:59:43.867 App[9151:907] Bouncing to 0.000000 over 20.000000 seconds.

何か案は?

アップデート

後世の場合、これは呼び出しsetNeedsUpdateConstraintslayoutIfNeeded子ビューで発生します。そうでないことを示唆するAppleのドキュメントにもかかわらず、スーパービューで呼び出す必要があります。これについては、以下の回答で詳しく説明しました。

ただし、代わりに @nielsbot の回答を受け入れました。私の質問に対する直接的な回答ではありませんが、私がやろうとしていたことを修正するよりも良い解決策です。

4

3 に答える 3

1

ビューを一時的にアニメーション化するためにコア アニメーションを使用できませんか?

ここで私の答えを参照してください: https://stackoverflow.com/a/9371196/210171

基本的に、アニメーション化したいビューで、そのレイヤーを取得し、それにアニメーションを追加します。レイヤーの変換をアニメーション化してこれを行う場合、ビューのサイズや位置は変更されず、レイアウト サイクルもトリガーされません。

CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:@"transform" ] ;
anim.values = @[ [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-5.0f, 0.0f, 0.0f) ], [ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(5.0f, 0.0f, 0.0f) ] ] ;
anim.autoreverses = YES ;
anim.repeatCount = 2.0f ;
anim.duration = 0.07f ;

[ viewToShake.layer addAnimation:anim forKey:nil ] ;
于 2013-10-29T20:51:51.233 に答える