UIScrollView. Любые мысли о реализации "бесконечной" прокрутки/масштабирования?
Таким образом, UITableView поддерживает существенно "бесконечную" прокрутку. Там может быть предел, но этот присоска может прокручиваться за время looonnnggg. Я хотел бы подражать этому поведению с помощью UIScrollView, но есть два основных препятствия:
1) scrollView.contentSize фиксируется во время создания.
2) масштабирование может привести к любой схеме ленивой загрузки в ад, поскольку это может вызвать взрыв инфантильных данных.
Разве другие мыслили эту идею? Я знаю, мы в основном говорим о создании Google Maps здесь. Любые идеи были бы оценены.
Cheers,
Дуг
Ответы
Ответ 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, сделайте трюк.
Чтобы смягчить возможность достижения конечного края и внезапного повторного просмотра представления (которое отменяет любую прокрутку, которая в настоящее время движется), представление может быть повторно перенесено, когда оно будет неподвижным, время от времени.
Во всяком случае, это то, что я собираюсь попробовать.