web-dev-qa-db-ja.com

iOS8アニメーションのバグ

ビューをアニメーション化する簡単な方法があります。

-(void)animateSelf
{
    CABasicAnimation * animation;

    animation = [CABasicAnimation animationWithKeyPath:@"position.y"];
    // settings ...
    [self.view.layer addAnimation:animation forKey:@"position.y"];

    animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    // settings ...
    [self.view.layer addAnimation:animation forKey:@"transform.rotation.z"];

    [UIView animateWithDuration: 1.0 animations:^{
        CGRect rect = self.view.frame;
        rect.Origin.y += 800;
        self.view.frame = rect;
    } completion:nil];
}

IOS7の場合はうまく機能しました。ただし、iOS 8の場合、アニメーションは予期しない動作をします。 iOS 8用にこれらのアニメーションを組み合わせる方法はありますか?

AnimateWithDuration:を別のCABasicAnimationに置き換えようとしましたが、役に立ちませんでした。 view.frameログは正しいですが、view.frameのアニメーションがあいまいなOriginからジャンプします。

CABasicAnimation for position.y(最初のもの)を削除すると、バグはなくなります。

22
Oleg Sobolev

3つのアニメーションがあります。

  1. レイヤーのpositionをアニメーション化します
  2. レイヤーのtransformをアニメーション化します
  3. ビューのframeをアニメーション化し、次にレイヤーのpositionをアニメーション化します。

アニメーション1と3が衝突します。

  • IOS 7では、アニメーション3がアニメーション1をキャンセルするという動作があります。
  • IOS 8での動作は、アニメーション1と3が同時に実行されることです(「追加アニメーション」)。

アニメーション1を削除し、関連する WWDC 2014 ビデオもチェックすることをお勧めします(Building Interruptible and Responsive Interactionsだったと思います)。

6
fluidsonic

私にとってうまくいったのは、アニメーションを実行する前のある時点で、ビューとビューのサブビューの自動レイアウトを無効にすることでした。 iOS8では、ストーリーボードから自動レイアウトを無効にするだけでは不十分でした。

[viewToAnimate removeFromSuperview];
[viewToAnimate setTranslatesAutoresizingMaskIntoConstraints:YES];
//addSubview again at original index
[superView insertSubview:viewToAnimate atIndex:index];
4
Rich Fox

この例はあなたを助けるかもしれません、私は時間を無駄にする前にそれを発見したと思います。 frameをアニメーション化するのではなく、そのcontraintsをアニメーション化します。調整したい自動レイアウト制約をクリックします(インターフェースビルダーで、トップ制約など)。次に、これをIBOutletにします。

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

上向きにアニメーション化します。

self.topConstraint.constant = -100;    
[self.viewToAnimate setNeedsUpdateConstraints]; 
[UIView animateWithDuration:1.5 animations:^{
    [self.viewToAnimate layoutIfNeeded]; 
}];

元の場所にアニメーションで戻す

self.topConstraint.constant = 0;    
[self.viewToAnimate setNeedsUpdateConstraints];  
[UIView animateWithDuration:1.5 animations:^{
    [self.viewToAnimate layoutIfNeeded];
}];

もともと私が投稿した ここ

したがって、例ではself.view.frameの制約を調整します。

2
DevC

また、iOS7とiOS8のアニメーションのちょっとした厄介な違いの問題もありました。ほとんどの場合、それは壊れていました:それは次のいずれかでした:

  • scale、Transform、RotateCGAffineTransformsの単一の組み合わせ-結果はiOSのバージョンに依存していました
  • または、さまざまなビューでのアニメーションの複雑なシーケンス-一部のビューは、新しいアニメーションを開始する前に位置を「リセット」していました。アニメーション作品の約5%が影響を受けました。

問題のあるビューでの同時アニメーションはなかったと確信しています。自動レイアウトと制約の提案は役に立ちませんでした(さらに、自動レイアウトはiOS8より前でもアニメーションに大きく干渉したため、すべてのアニメーションビューはコードで作成されました)。

両方の問題の普遍的な解決策であることが判明したのは、問題のあるビューをラッパービューに入れ、それを使用して回転アニメーションを分割するか、「リセット」効果を引き起こすアニメーションを実行することです。現在、7.1.1と8.1.1で同じように機能します。

0
Yana