Подтвердить что ты не робот

UIScrollView. Любые мысли о реализации "бесконечной" прокрутки/масштабирования?

Таким образом, UITableView поддерживает существенно "бесконечную" прокрутку. Там может быть предел, но этот присоска может прокручиваться за время looonnnggg. Я хотел бы подражать этому поведению с помощью UIScrollView, но есть два основных препятствия:

1) scrollView.contentSize фиксируется во время создания. 2) масштабирование может привести к любой схеме ленивой загрузки в ад, поскольку это может вызвать взрыв инфантильных данных.

Разве другие мыслили эту идею? Я знаю, мы в основном говорим о создании Google Maps здесь. Любые идеи были бы оценены.

Cheers, Дуг

4b9b3361

Ответ 1

В то время как невозможно иметь по-настоящему бесконечный UIScrollView, есть несколько простых трюков, которые вы можете использовать для эмуляции этого поведения.

  • Обработка фиксированного contentSize: иметь вид фиксированного размера, обрабатываемый вашим представлением прокрутки, а при запуске или создании экземпляра установите смещение содержимого так, чтобы вы видели середину обработанного вида. Затем просто просмотрите смещение содержимого (используя KVO или какой-либо другой метод), и если вы приближаетесь к любому краю, обновите содержимое представления с помощью нового набора контента (смещение соответственно) и reset свойства прокрутки contentOffset, чтобы вернитесь посередине.
  • Обработка масштабирования: сделайте что-то подобное, только на этот раз просмотрите коэффициент масштабирования в режиме прокрутки. Всякий раз, когда это доходит до определенной точки, делайте некоторые манипуляции с любыми данными, которые вы представляете, чтобы они отображались, а затем reset коэффициент масштабирования до 1.0. Например, если вы прокручиваете изображение, и оно увеличивается, чтобы отображаться в два раза больше, программно применяйте какое-то преобразование, чтобы сделать изображение вдвое большим, а затем reset коэффициент масштабирования прокрутки до 1.0. Изображение будет по-прежнему отображаться увеличенным, но просмотр прокрутки сможет продолжить масштабирование, если необходимо. (Google Maps делает этот шаг еще дальше, когда он лениво загружает более подробные представления при масштабировании пользователя - вы можете или не можете его реализовать).

Ответ 2

Я только что закончил реализацию прокрутки infitine для меня. В моей реализации у меня есть UITableViewCell с scrollView и Navigationbuttons. ScrollView содержит x просмотра всех с одинаковой шириной. представления отображаются горизонтально, а пейджинг включен.

scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;

Моя кодология выглядит следующим образом:

  • В моей функции инициализации I
    • создать все представления (для прокрутки) и
    • помещаем их в массив и
    • добавьте их в scrollView
  • Затем я вызываю функцию, которая вычисляет в цикле позиции для каждого представления (каждый раз, когда вы обнаруживаете прокрутку, эта функция также должна быть вызвана). Он всегда принимает первый элемент массива и устанавливает кадр в (0,0,...,...), второй с (i * width, 0,....,....) и так на. Вызываемая функция выглядит следующим образом:

    - (void)updateOffsetsOfViews{
        int xpos = 0;
        for (int i=0; i<[views count]; i++) {
            UIImageView *_view = [views objectAtIndex:i];
            CGRect aFrame = _view.frame;
            aFrame.origin.x = xpos;
            aFrame.origin.y = 0.0;
            _view.frame = aFrame;
            xpos += viewWidth;
        }
        float center = 0;
        if(fmod([views count],2) == 1){
            center = viewWidth * ([views count]-1)/2;
        }else {
            center = viewWidth * [views count]/2;
        }
        [scrollView setContentOffset:CGPointMake(center, 0)];
        lastOffset = center;
    }
    
  • Затем (все еще в процессе инициализации) добавляю наблюдателя

    [scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:nil];
    

    поэтому каждый раз, когда что-то изменяется в scrollView, я получаю вызванную функцию (observValueForKeyPath), которая выглядит следующим образом:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object  change:(NSDictionary *)change context:(void *)context
    {
        UIImageView *_viewFirst = (UIImageView *)[views objectAtIndex:0];
        if ( fmod([scrollView contentOffset].x,viewWidth)  == 0.0) {
            if ([scrollView contentOffset].x > lastOffset) {
                [views removeObjectAtIndex:0];
                [views addObject:_viewFirst];                
                [self updateOffsetsOfViews];    
            }else if ([scrollView contentOffset].x < lastOffset) {
                UIImageView *_viewLast = (UIImageView *)[views lastObject];
                [views removeLastObject];
                [views insertObject:_viewLast atIndex:0];            
                [self updateOffsetsOfViews];
            }
        }
    }
    
  • И в dealloc или viewDidUnload (в зависимости от того, как вы его реализуете) не забудьте удалить наблюдателя.

    [scrollView removeObserver:self forKeyPath:@"contentOffset"];   
    

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

Ответ 3

Проект StreetScroller от Apple демонстрирует, как выполнять бесконечную прокрутку в UIScrollView.

Ответ 4

Имейте в виду, что при анимации прокрутки contentOffset изменяется много раз, а не только по страницам, но с каждым шагом в анимации.

Ответ 5

Возможно, установив contentSize в какое-то гигантское значение, а затем перемещая ограниченное количество основных видов вокруг, чтобы отслеживать позицию вида, как в примере Tiling, сделайте трюк.

Чтобы смягчить возможность достижения конечного края и внезапного повторного просмотра представления (которое отменяет любую прокрутку, которая в настоящее время движется), представление может быть повторно перенесено, когда оно будет неподвижным, время от времени.

Во всяком случае, это то, что я собираюсь попробовать.