0

現在、UIプラグインを作成しています。このプラグインには2つのimageViewがあり、1つは別のものの上にあります。

ユーザーが画面をスワイプした場合:スワイプがしきい値よりも大きい場合、前面のimageViewは画面をスワイプと同じ方向に残し、背面のimageViewの後ろに表示されます。

したがって、これを画像のキューに使用する予定です。スワイプが成功すると、前面のimageViewが画面を離れ、backImageView(現在は前面)の後ろの中央に配置され、内部の画像が変更されます。

画像がなくなったら、サーバーからさらに画像をダウンロードしていることを示すスピナーを表示します。

説明できないバグが1つ発生しています。ビューにスピナーを追加すると、アニメーションが誤動作します。

スワイプされたimageViewは画面を離れなくなり、元の位置に戻ります。

私たちはこれに非常に戸惑い、次のことを確認しました

                 [self.view addSubview:spinner];

アニメーションに予期しない動作が発生します。

添付の移動方法を細かくしてください:

- (void)move:(UIPanGestureRecognizer *)sender {
    CGPoint translatedPoint = [sender translationInView:self.frontView];

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
        _firstX = self.frontView.center.x;
        _firstY = self.frontView.center.y;
    }

    translatedPoint = CGPointMake(_firstX+translatedPoint.x, _firstY+translatedPoint.y);
    [self.frontView setCenter:translatedPoint];

    if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
        // Calculate the if the x-movement is greater than a threshold
        float xTravelled = 0;
        if (self.frontView.center.x > _firstX)
            xTravelled = self.frontView.center.x - _firstX;
        else
            xTravelled = _firstX - self.frontView.center.x;

        // Only move if xTravelled is greater than threshold
        if (xTravelled > self.frontView.window.frame.size.width / 3) {
            NSLog(@"Swipe detected, currentIndex:%d", currentIndex);

            // Lock view from panning until animation is finished.
            self.view.userInteractionEnabled = NO;

            float newXPosition;
            if (self.frontView.center.x > _firstX) {
                newXPosition = (float) self.view.frame.size.width * 2;
            } else {
                newXPosition = (float) -2 * self.view.frame.size.width;
            }

            // We should trigger a fetch as soon as the back image is empty.
            if (![self getBackView].image) {
                double delayInSeconds = 2.0;
                dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
                dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                    //[self fetchComplete];
                    [spinner stopAnimating];
                    [spinner removeFromSuperview];
                    self.view.userInteractionEnabled = YES;
                });

                // Pop up spinner if necessary
                if (![spinner isAnimating]) {
                    self.view.userInteractionEnabled = NO;
                    [spinner setCenter:CGPointMake(_firstX, _firstY)];
                    [spinner startAnimating];
                    /* THIS BREAKS OUR ANIMATION - Enable it to see 
                     [self.view addSubview:spinner];
                     */
                }
            }

            // Animate the rest of the swipe
            [UIView \
             animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionTransitionNone
             animations:^{
                 // Use smooth animation to move the top image out of the way
                 [self.frontView setCenter:CGPointMake(newXPosition, self.frontView.center.y)];
             }
             completion:^(BOOL finished){
                 // Set it to be physically behind the back image
                 [self.view sendSubviewToBack:self.frontView];
                 //[self.frontView setCenter:CGPointMake(_firstX, _firstY)];  // why not necessary??

                 // Now change the picture
                 UIImage *next = [self nextImage];
                 self.frontView.image = next;

                 // update self.top to reference the new back image
                 self.frontView = [self getBackView];

                 // Do not override spinner's block 
                 if (![spinner isAnimating])
                     self.view.userInteractionEnabled = YES;
             }];
        } else {
            NSLog(@"Swipe NOT detected");
            [UIView \
             animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction
             animations:^{
                 [self.frontView setCenter:CGPointMake(_firstX, _firstY)];
             } completion:^(BOOL finished) {
                 self.view.userInteractionEnabled = YES;
             }];
        }
    }

これはかなり長いことは理解していますが、このバグをサンプルプロジェクトに分離し、ダウンロードしてコンピューターに実行できるようにしました。このサンプルプロジェクトはここにあります:http://bit.ly/WO4cEI

self.viewにサブビューを追加すると、[self.view sendSubviewToBack:self.frontView]が失敗する原因になっていると思われます。しかし、これがアニメーションの失敗の原因である理由もわかりません。

助けてくれてありがとう!!

編集

@user2113425の推奨によりこの問題が修正されました!!

4

2 に答える 2

1

まず第一に、とにかくその時点でスピナーを追加する必要はありません。

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(move:)];
    [panRecognizer setMinimumNumberOfTouches:1];
    [panRecognizer setMaximumNumberOfTouches:1];

    [panRecognizer setDelegate:self];
    [self.view addGestureRecognizer:panRecognizer];
    self.view.userInteractionEnabled = YES;

    // Index starts at zero so we pick even.
    self.frontView = self.evenImage;

    // Setting the images
    images = [[NSArray alloc] initWithObjects:@"a.jpeg", @"b.jpeg", nil]; // @"c.jpeg", @"d.jpeg", @"e.jpeg", nil];

    currentIndex = 0;
    self.evenImage.image = [self nextImage];
    self.oddImage.image = [self nextImage];

    // Spinner
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    **spinner.hidesWhenStopped = YES;
    [self.view addSubview:spinner];**
}

viewDidLoadにスピナーを追加し、hidesWhenStoppedを設定して非表示にし、move関数で[spinnerremoveFromSuperview]を削除できます。この行。

addSubViewの問題は、サブビューのzorderを変更することです。これに関係している可能性がありますが、確かではありません。

この問題を解決する方法はたくさんあります。

于 2013-03-06T00:57:36.860 に答える
0

その理由は、スピナーのアニメーションである可能性があります。viewControllerに高周波を更新するtableViewが含まれている場合にも同じ現象が発生します。レイヤーの再描画によりアニメーションが中断されます。スピナーがビューのサブビューになる場合は、このような現象が発生します。

于 2013-03-06T02:02:43.783 に答える