-2

私は現在、iOS 開発の最初の不安定な一歩を踏み出しています。自由落下するボールをアニメーション化しようとしています。IBAction に接続されたボタンと、ボールの画像を含む UIImageView があります。

私のアクション内には、NSTimeInterval を使用して時間を計る while ループがあり、かかる時間に基づいて、ボールが「地面」に到達するまでの新しい位置を計算します (はい、これはおそらく最適な方法ではないことを認識しています。しかし、私は構文を理解するのに苦労しています (そして、私の問題はおそらくそこにあります)。最適化は後で行う必要があります)。私が理解できることから、 NSTimeInterval は経過時間を秒単位で返すため、信じられないほど小さなステップで増加しますが、機能するはずです。しかし、脳のおならの深刻なケースがあるかもしれません。

ここまでは順調ですね。しかし、ボタンをタップすると、ボールはアニメーションなしで開始点から終了点までまっすぐに移動します。

-(IBAction)doshit:(id)sender{

int G = 10;
CGPoint center = [myImage center];
NSDate *startTime = [NSDate date];
NSTimeInterval T;

T = fabs([startTime timeIntervalSinceNow]);
while (center.y<480)
{

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:T];

    center.y=center.y+((G*T*T)/2);
    [myImage setCenter:center];

    T = fabs([startTime timeIntervalSinceNow]);
    [UIView commitAnimations];
}

}

私はすべての提案を歓迎します!=)

4

2 に答える 2

0

これを行う 1 つの方法は、CADisplayLink を使用してタイミングを提供することです。これは、1/60 秒のディスプレイ リフレッシュ レートに関連付けられています。自動レイアウト (現在はデフォルトでオンになっています) を使用している場合は、フレームを設定するよりも、制約をアニメーション化することをお勧めします。そのため、この例では画面上部のボタンを使用しており、ビューの上部への制約は IBOutlet topCon に接続されています。

#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (weak,nonatomic) IBOutlet NSLayoutConstraint *topCon;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(startDisplayLink) withObject:nil afterDelay:2];
}

- (void)startDisplayLink {
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}

- (void)stopDisplayLink {
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink {
    static BOOL first = YES;
    static double startTime = 0;
    if (first) {
        startTime = displayLink.timestamp;
    }
    first = NO;
    double T = (double)displayLink.timestamp - startTime;
    self.topCon.constant += ((10 * T * T)/2);
    if (self.topCon.constant > 420) {
        [self stopDisplayLink];
    }
}
于 2013-03-26T02:07:37.900 に答える
0

Carl が指摘しているように、メソッド呼び出しの途中で何かを繰り返し変更してアニメーションを実行することはできません。UIView を強制的に再描画する最も堅牢な方法は何ですか? を参照してください。それについての詳細な議論のために。

ご想像のとおり、これは最適ではないだけでなく、積極的に iOS と戦います。iOS には、あらゆる種類のタイマーに頼らずにスムーズなアニメーションを実行するための使いやすいテクニックがたくさんあります。簡単なアプローチの 1 つを次に示します。

- (IBAction)dropAnimate:(id)sender {
  [UIView animateWithDuration:3 animations:^{
     self.circleView.center = CGPointMake(100, 300);
   }];
}

ブロックではanimations、変更したいものを最終値に変更します(myImage.centerあなたの場合)。UIKit は現在の値と最終的な値をサンプリングし、要求された時間内に到達するためのパスを見つけます。他のいくつかの機能 (連鎖アニメーションなど) を備えた完全で実行可能な例については、iOS:PTL Chapter 9 のサンプル コードを参照してください。

上記のコードは、デフォルトのタイミング関数を使用します。それを理解したら、タイミング機能のカスタマイズに進むことができます。アニメーションの種類とタイミングのプログラミング ガイドのアニメーションのペーシングを参照してください。また、Core Animation でカスタム イージング関数を作成する方法は? Core Animationのパラメトリック加速曲線。ただし、最初に単純なデフォルトのアニメーションについて理解してもらいたいと思います。

于 2013-03-26T02:20:41.973 に答える