2011-07-24 3 views
-2

мне нужна помощь с реализацией UIScrollView со следующими требованиями:Paged UIScrollView с ленивой задержкой загрузкой

1) pagingEnabled = верно.
2) загрузка ленивых страниц.
3) страницы загружаются в фоновом режиме. Поэтому мне нужно сначала запустить загрузку страницы X, затем получить уведомление о том, что страница полностью загружена и только затем разрешить пользователю прокручивать ее.
4) возможность изменения текущей страницы.

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

Моя вторая попытка состояла в том, чтобы переопределить метод layoutSubviews UIScrollView и выполнить все вычисления там. Но это кажется очень сложным.

Итак, я хотел бы найти примеры подобных реализаций.

Теперь у меня есть такой код:

Я реализовал scrollViewWillBeginDragging и scrollViewDidEndDecelerating:

- (void)scrollViewWillBeginDragging:(UIScrollView *)aScrollView 
{ 
    isScrolling = YES; 
} 
- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView 
{ 
    isScrolling = NO; 
    // Here we load the page that was prepared when the user was scrolling 
    if (needDisplay > -1) { 
     //NSLog(@"Loading queued page %d", needDisplay); 
     [self loadScrollViewWithPage:needDisplay forceAddToSuperview:NO animated:YES]; 
     needDisplay = -1; 
    } 

    // minLoadedPageIndex - index of the first loaded page. 
    int selectedIndex = MIN(floor((aScrollView.contentOffset.x - pageWidth/2)/pageWidth) + 1 + minLoadedPageIndex, [photoItems count] - 1); 

    [self loadScrollViewWithPage:selectedIndex - 1 forceAddToSuperview:NO animated:YES]; 
    [self loadScrollViewWithPage:selectedIndex forceAddToSuperview:NO animated:YES]; 
    [self loadScrollViewWithPage:selectedIndex + 1 forceAddToSuperview:NO animated:YES]; 
} 

В loadScrollViewWithPage Я создаю вид контроллера страницы, который загружает данные с сервера в фоновом режиме. Я не добавляю представление в scrollview, пока он не загрузит данные с сервера.

- (void)loadScrollViewWithPage:(int)page forceAddToSuperview:(BOOL)value animated:(BOOL)animated 
{ 
    DetailController *controller = page >= viewControllers.count ? [NSNull null] :[viewControllers objectAtIndex:page]; 

    if ((NSNull *)controller == [NSNull null]) 
    { 
     controller = [[DetailController alloc] initWithNibName:@"DetailController" bundle:nil];   
     controller.delegate = self; 
     controller.view.hidden = NO; //this will call viewDidLoad. 

     if (page >= viewControllers.count) { 
      [viewControllers addObject:controller]; 
     } 
     else { 
      [viewControllers replaceObjectAtIndex:page withObject:controller]; 
     } 

     [controller release]; 
    } 

    // add the controller's view to the scroll view 
    if (controller.view && controller.view.superview == nil && (controller.isLoadedOrFailed || value)) { 
     [self setNumberOfVisiblePages:visiblePagesCount+1]; 

     if (page < selectedIndex) { 
      // We are adding the page to the left of the current page, 
    // so we need to adjust the content offset. 
      CGFloat offset = (int)scrollView.contentOffset.x % (int)scrollView.frame.size.width; 
      offset = scrollView.frame.size.width * (selectedIndex - minLoadedPageIndex) + offset; 
      [scrollView setContentOffset:CGPointMake(offset, 0.0) animated:animated];  
     } 

     CGRect frame = scrollView.frame; 
     frame.origin.x = frame.size.width * (page - minLoadedPageIndex); 
     frame.origin.y = 0; 
     controller.view.frame = frame;   
     [scrollView addSubview:controller.view]; 
     [controller viewWillAppear:NO]; 
    } 
} 

Также у меня есть метод detailControllerDidFinishDownload который вызывается, когда данные для контроллера представления страницы были загружены.

- (void)detailControllerDidFinishDownload:(DetailController *)controller 
{ 

    ... //here I calculate new minLoadedPageIndex value 

// reset pages frames 
if (minLoadedPageIndex < oldMinPage) { 
     for(int i=oldMinPage;i < [viewControllers count]; i++) { 
      DetailController *detailsController = [viewControllers objectAtIndex:i]; 
      if ((NSNull *)detailsController != [NSNull null]) { 
       CGRect frame = scrollView.frame; 
       frame.origin.x = frame.size.width * (i - minLoadedPageIndex); 
       frame.origin.y = 0; 

       [detailsController.view setFrame:frame]; 
      } 
     } 
    } 

    // load the page now or delay load until the scrolling will be finished 
    if (!isScrolling) { 
     [self loadScrollViewWithPage:[photoItems indexOfObject:controller.photoItem] forceAddToSuperview:NO animated:NO]; 
    } 
    else { 
     needDisplay = [photoItems indexOfObject:controller.photoItem]; 
     //NSLog(@"pageControlUsed is used!!! %d", [photoItems indexOfObject:controller.photoItem]); 
    } 
} 

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

Спасибо, Михаил!

+0

Я отбросил требование, чтобы пользователь не мог прокручивать страницы во время загрузки; показание индикатора прогресса кажется гораздо более удобным для пользователя и не требует нарушения поведения UIScrollView почти так же. –

+0

Мой клиент хочет этого, и я не могу убедить его отказаться от него :( – MrZoidberg

ответ

1

Есть много вещей, которые вам требуются в то же время. Я предлагаю вам взглянуть на этот пример.

http://ykyuen.wordpress.com/2010/05/22/iphone-uiscrollview-with-paging-example/

Это очень хорошая отправная точка.

+0

Знаете, это не я, кто правит игрой. Спасибо! – MrZoidberg

+0

Этот пример слишком прост. Я сделал на 500% больше, чем в этом примере. – MrZoidberg

+0

Трудно понять, что вы сделали, а не потому, что код не отображается. –

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