2014-09-26 2 views
27

Я выполнил собственный элемент управления обновлением (мой собственный класс, а не подкласс), и по какой-то причине, начиная с перехода на iOS 8, устанавливая contentInset прокрутки (в частности, UICollectionView), чтобы запустить обновленная анимация вызывает странный прыжок/заикание. Вот мой код:Анимация UIScrollView contentInset вызывает скачкообразное замедление

- (void)containingScrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat scrollPosition = scrollView.contentOffset.y + scrollView.contentInset.top; 

    if(scrollPosition > 0 || self.isRefreshing) 
    { 
     return; 
    } 

    CGFloat percentWidth = fabs(scrollPosition)/self.frame.size.height/2; 

    CGRect maskFrame = self.maskLayer.frame; 

    maskFrame.size.width = self.imageLayer.frame.size.width * percentWidth; 

    [CATransaction begin]; 
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; 
    self.maskLayer.frame = maskFrame; 
    [CATransaction commit]; 
} 

- (void)containingScrollViewDidEndDragging:(UIScrollView *)scrollView 
{ 
    if((self.maskLayer.frame.size.width >= self.imageLayer.frame.size.width) && !self.isRefreshing) 
    { 
     self.isRefreshing = YES; 
     [self setLoadingScrollViewInsets:scrollView]; 
     [self startAnimation]; 
     [self sendActionsForControlEvents:UIControlEventValueChanged]; 
    } 
} 

- (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView 
{ 
    UIEdgeInsets loadingInset = scrollView.contentInset; 
    loadingInset.top += self.frame.size.height; 

    UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState; 

    [UIView animateWithDuration:0.2 delay:0 options:options animations:^ 
    { 
     scrollView.contentInset = loadingInset; 
    } 
    completion:nil]; 
} 

В основном когда пользователь отпускает обновить, я анимировать contentInset на высоту контроля обновления. Я полагаю, что анимация уменьшила бы заикание/прыткость, что и в iOS 7. Но в iOS 8, когда scrollView освобождается от перетаскивания, вместо того, чтобы просто анимировать содержимое ContentInset, содержимое представления прокрутки скачкообразно падает с точки выпуска быстро, а затем анимирует плавно. Я не уверен, что это ошибка в iOS 8 или что-то еще. Я также попытался добавить:

scrollView.contentOffset = CGPointZero; 

в блоке анимации, который ничего не менял.

У кого-нибудь есть идеи? Любая помощь будет высоко оценен. Благодаря!

ответ

23

Я изменил метод с моей анимации блока:

- (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView 
{ 
    UIEdgeInsets loadingInset = scrollView.contentInset; 
    loadingInset.top += self.view.frame.size.height; 

    CGPoint contentOffset = scrollView.contentOffset; 

    [UIView animateWithDuration:0.2 animations:^ 
    { 
     scrollView.contentInset = loadingInset; 
     scrollView.contentOffset = contentOffset; 
    }]; 
} 
+2

Работал для меня! Ты жжешь. Спасибо, что поставили это здесь. – boztalay

+2

Вы правы, это исправляет проблему. Похоже, что анимация только содержимогоInset вызывает анимацию, которая мешает анимации замедления, поэтому появляется «прыжок». Включение contentOffset запускает анимацию с текущей позиции. –

+0

Включая смещение содержимого в анимации, кажется довольно сложно угадать. Как вы это определили? – Tudorizer

2

У меня была такая же проблема, и переместил мой анимации блок к ...

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView

метод делегата вместо. Не идеально, но я пока не могу определить проблему. Похоже, что метод scrollView -layoutSubviews чаще всего вызывается под iOS8, вызывая оживленную анимацию.

+0

Я попытался сдвинув его в там, но это, кажется, не дают желаемого эффекта, к сожалению ... – ryanthon

+1

Это решение работает для меня. Чтобы быть точным, я переместил настройку 'scrollView.contentInset' (внутри' animateWithDuration: ') из' scrollViewDidEndDragging: willDecelerate: 'to' scrollViewWillBeginDecelerating: ' – jonsibley

5
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ 
    CGPoint point = scrollView.contentOffset; 

    static CGFloat refreshViewHeight = 200.0f; 

    if (scrollView.contentInset.top == refreshViewHeight) { 
     //openning 
     if (point.y>-refreshViewHeight) { 
      //will close 
      //必须套两层animation才能避免闪动! 
      [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) { 
       [UIView animateWithDuration:0.25 animations:^{ 
        scrollView.contentOffset = CGPointMake(0.0f, 0.0f); 
        scrollView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); 
       } completion:NULL]; 
      }]; 

     } 
    } 
    else{ 
     //closing 
     static CGFloat openCriticalY = 40.0f;//会执行打开的临界值 
     if(point.y<-openCriticalY){ 
      //will open 
      [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) { 
       [UIView animateWithDuration:0.25 animations:^{ 
        scrollView.contentInset = UIEdgeInsetsMake(refreshViewHeight, 0.0f, 0.0f, 0.0f); 
        scrollView.contentOffset = CGPointMake(0.0f, -refreshViewHeight); 
       } completion:NULL]; 
      }]; 
     } 
    } 
} 

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

+0

Этот ответ работает на меня на iOS9.2 – liaa

+0

В моем приложении с iOS9.0 для удаления прыжка не требуется блок анимации, просто сбросьте содержимое. После установки contentInset выполнит трюк. Однако, если вы хотите контролировать скорость прокрутки tableVIew при скрытии представления обновления, двойные блоки анимации будут делать магию, одного блока анимации недостаточно. –

+0

Можете ли вы объяснить, как работают блоки двойной анимации? Благодарю. –

2

Два решения:

  1. отключить отказов при запуске загрузки и включить отскок после завершения загрузки
  2. после установки содержимого вставка при запуске загрузка, пожалуйста, установить содержание смещения с постоянным значением
+0

Переключение отказов не работает. Но установка contentOffset на его значение перед установкой contentInset работает как шарм. Блок анимации не требуется. Причиной этой проблемы является то, когда установлен параметр contentInset, для contentOffset также установлено значение в соответствии с новым значением contentInset. Поэтому восстановление contentOffset до его старого значения после установки contentInset решает проблему. –

3

К удалите прыжок, ответ ryanthon сделает трюк. В моем приложении с iOS9.0 никакой блок анимации даже не требуется, чтобы удалить скачок, просто сбросив контентОффсет после установки contentInset будет делать трюк.

Если вы хотите контролировать скорость прокрутки таблицыView при скрытии вида обновления, двойной трюк блоков анимации в ответе пользователя3044484 будет делать магию, одного блока анимации недостаточно.

if (self.tableView.contentInset.top == 0) 
{ 
    UIEdgeInsets tableViewInset = self.tableView.contentInset; 
    tableViewInset.top = -1.*kTableHeaderHeight; 
    [UIView animateWithDuration: 0 animations: ^(void){} completion:^(BOOL finished) { 
     [UIView animateWithDuration: 0.5 animations:^{ 
     //no need to set contentOffset, setting contentInset will change contentOffset accordingly. 
      self.tableView.contentInset = tableViewInset; 
     }]; 
    }]; 
} 
+0

Может кто-нибудь объяснить, как работают блоки двойной анимации? –

+0

Это довольно неожиданно, но на самом деле это работает, не уверенный, как двойной блок анимации может вызвать различное поведение –

1

Я разрешаться: -

  • Отключения Ошибки при ContentInset обновляется до contentOffsetY.
  • Следите за содержимымОфис и обновите таблицу TableViewInformation.
var contentOffsetY:CGFloat = 100 
    func tracScrollContent(location: UIScrollView) { 
     if(location.contentOffset.y == -contentOffsetY) { 
      tblView.isScrollEnabled = true 
      tblView.bounces = false 
      tblView.contentInset = UIEdgeInsets(top: contentOffsetY, left: 0, bottom: 0, right: 0) 
     }else if(location.contentOffset.y >= 0){ 
      tblView.bounces = true 
      tblView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 
     } 
    } 

Github Demo Swift-3

Смежные вопросы