2013-10-06 13 views
10

更新:私はまだこの問題を解決したいと思いますが、animateWithDuration:delay:options:animations:completion:に切り替わりました。これはもっとうまく動作します。それは春が与える最後の素晴らしい "バウンス"が欠けていますが、少なくともそれは制御可能です。UIPanGestureRecognizerの速度が速すぎるUIViewアニメーション


私は、iOS用の素敵なジェスチャー駆動型UIを作成しようとしていますが、値は素敵な自然な感じのアプリをもたらすようになっていくつかの困難に実行しています。

私は弾力のある春のアニメーションが好きなのでanimateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:を使用しています。私はvelocity引数を、完成した状態のジェスチャ認識器によって与えられた速度で初期化しています。問題は、私がすばやくパンを動かして放して、速度が数千に及ぶと、私の見解が画面から飛んで終わり、そしてそのような目を見張るような復讐で前後にバウンスすることです。

私は、ビューが移動する必要がある距離の長さに対してアニメーションの時間幅を調整しています。そのため、必要なピクセルがほんの少しの場合、アニメーションにかかる時間が短くなります。しかし、それは問題を解決しませんでした。それはまだナッツに終わる。

私がを望むのは、ユーザーがドラッグしている速度でビューを開始する必要がありますが、ターゲットポイントに到達するとすばやく減速し、最後に少しだけバウンスする必要があります速度が妥当なものであれば)。

このメソッドまたは値を正しく使用しているのだろうかと思います。ここに私が何をしているかを示すコードがあります。どんな助けもありがとう!

- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture { 
    CGPoint offset = [gesture translationInView:self.view]; 
    CGPoint velocity = [gesture velocityInView:self.view]; 

    NSLog(@"pan gesture state: %d, offset: %f velocity: %f", gesture.state, offset.x, velocity.x); 
    static CGFloat initialX = 0; 

    switch (gesture.state) { 
     case UIGestureRecognizerStateBegan: { 
      initialX = self.blurView.x; 
     break; } 

     case UIGestureRecognizerStateChanged: { 
      self.blurView.x = initialX + offset.x; 
     break; } 

     default: 
     case UIGestureRecognizerStateCancelled: 
     case UIGestureRecognizerStateEnded: { 
      if (velocity.x > 0) 
       [self openMenuWithVelocity:velocity.x]; 
      else 
       [self closeMenuWithVelocity:velocity.x]; 
     break; } 
    } 
} 

- (void)openMenuWithVelocity:(CGFloat)velocity { 
    if (velocity < 0) 
     velocity = 1.5f; 

    CGFloat distance = -40 - self.blurView.x; 
    CGFloat distanceRatio = distance/260; 
    NSLog(@"distance: %f ratio: %f", distance, distanceRatio); 

    [UIView animateWithDuration:(0.9f * distanceRatio) delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:velocity options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 
     self.blurView.x = -40; 
    } completion:^(BOOL finished) { 
     self.isMenuOpen = YES; 
    }]; 
} 

答えて

12

関連する問題の解決策を探しています。

初期の春速度:問題はあなたが- animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completionが望んでいる...少しオダー値を/秒の点であるUIPanGestureRecognizerから速度、に渡している、です。アニメーションをスムーズに開始するには、この値をアタッチする前のビューの速度と一致させます。 値1は、1秒間に移動する合計アニメーション距離に対応します。たとえば、アニメーションの総距離が200ポイントで、アニメーションの開始点をビュー速度100pt/sに一致させるには、値0.5を使用します。

アニメーション方法では、毎秒のポイントではなく、毎秒の「距離」で速度を求めています。したがって、渡すべき値は(ジェスチャ認識器からのベロシティ)/(アニメーション中に移動した合計距離)です。

これはまさに私がやっていることであり、ジェスチャ認識プログラムが動かしているときとアニメーションがピックアップしているときの間に、まだ目立っていない "ヒカップ"が残っているという。それは、あなたが以前に持っていたものよりもはるかにうまくいくはずです。

+0

ちょっとインナースプリング速度を正しく使う方法を見つけましたか? – bogardon

+0

1つのフレームのしっかりとした出荷を終えた... – Arclite

2

まず、アニメーションが処理しなければならない残りの距離を計算する必要があります。あなたがUIViewAnimationOptionCurveLinearを使用しなければならないクリーンな速度転送用

CGFloat springVelocity = fabs(gestureRecognizerVelocity/distanceToAnimate); 

:あなたは、デルタ距離を持っているときには、このような速度を計算に進むことができます。

0

私は少し違っていましたが、パンのベロシティ/パンの変換に基づいて、私のコード、すなわちベロシティ計算に役立つかもしれません。

コンテキストのビット:私はUIViewの側でpanGestureRecognizerを使用してサイズを変更する必要がありました。

  • iPadがポートレートモードにある場合、ビューは、左、底 及び右側に取り付けられ、そしてIは サイズを変更するためにビューの上部境界上にドラッグされています。
  • iPadがランドスケープモードの場合、ビューは の左、上、下の辺に添付され、右の枠にドラッグしてサイズを変更します。

Landscape

Portrait

これは私がUIPanGestureRecognizerためIBActionで使用したものである:助け

var velocity: CGFloat = 1 

    switch gesture.state { 
     case .changed: 
     // Adjust the resizableView size according to the gesture translation 
     let translation = gesture.translation(in: resizableView) 
     let panVelocity = gesture.velocity(in: resizableView) 

     if isPortrait { // defined previously in the class based on UIDevice orientation 

      let newHeight = resizableViewHeightConstraint.constant + (-translation.y) 
      resizableViewHeightConstraint.constant = newHeight 

      // UIView animation initialSpringVelocity requires a velocity based on the total distance traveled during the animation 
      velocity = -panVelocity.y/-panTranslation.y 

     } else { // Landscape 
      let newWidth = resizableViewWidthConstraint.constant + (translation.x) 

      // Limit the resizing to half the width on the left and the full width on the right 
      resizableViewWidthConstraint.constant = min(max(resizableViewInitialSize, newWidth), self.view.bounds.width) 

      // UIView animation initialSpringVelocity requires a velocity based on the total distance traveled during the animation 
      velocity = panVelocity.x/panTranslation.x 
     } 

     UIView.animate(withDuration: 0.5, 
         delay: 0, 
         usingSpringWithDamping: 1, 
         initialSpringVelocity: velocity, 
         options: [.curveEaseInOut], 
         animations: { 
         self.view.layoutIfNeeded() 
         }, 
         completion: nil) 

     // Reset translation 
     gesture.setTranslation(CGPoint.zero, in: resizableView) 
} 

希望。

関連する問題