UIView Animation не работает при добавлении счетчика?

В настоящее время я создаю плагин пользовательского интерфейса. Этот плагин имеет 2 изображения, один поверх другого.

Когда пользователь проводит пальцем по экрану: если пролистывание превышает пороговое значение, переднее представление изображения покидает экран в том же направлении, что и пролистывание, а затем появляется за задним изображением.

Поэтому мы планируем использовать это для очереди изображений. После успешного смахивания переднее изображение покинет экран, затем переместится в центр за задним изображением (теперь передним), а затем изменит изображение внутри.

Когда изображений больше нет, я включаю счетчик, чтобы указать, что мы загружаем больше изображений с сервера.

Мы столкнулись с одной ошибкой, которую не могли объяснить сами: когда мы добавляем счетчик в наше представление, наша анимация дает сбой.

Сдвинутый 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 устранила эту проблему!!


person disappearedng    schedule 06.03.2013    source источник


Ответы (2)


Прежде всего, вам не нужно добавлять счетчик в этот момент.

- (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, чтобы скрыть его, а в функции перемещения удалить [spinner removeFromSuperview]; эта линия.

Проблема с addSubView заключается в том, что он изменяет zorder подвидов, это может быть связано с этим, но не уверен.

есть много способов решить эту проблему..

person andykkt    schedule 06.03.2013

Причиной может быть анимация спиннера. То же самое явление возникает, когда viewController содержит tableView, который обновляется с высокой частотой. Повторная отрисовка слоя прерывает анимацию. Если счетчик становится подвидом представления, происходит такое явление.

person junkor    schedule 06.03.2013