Установка contentOffset программно запускает scrollViewDidScroll
у меня есть несколько UIScrollView
на странице. Вы можете прокручивать их независимо или блокировать их вместе и прокручивать их как один. Проблема возникает, когда они заблокированы.
я использую UIScrollViewDelegate
и scrollViewDidScroll:
отслеживать движение. Я спрашиваю contentOffset
на UIScrollView
который изменился, а затем отражает изменение других видов прокрутки, установив их contentOffset
свойства, чтобы соответствовать.
большой.... только я заметила много лишних звонков. Программно изменяя contentOffset
мой свиток представления запускают метод делегата scrollViewDidScroll:
называться. Я пробовал использовать setContentOffset:animated:
вместо этого, но я все еще получаю триггер на делегате.
как я могу изменить мои contentOffsets программно, чтобы не запускать scrollViewDidScroll:
?
заметки....
Каждый UIScrollView
является частью пользовательского UIView
который использует шаблон делегата для возврата к представлению UIViewController
подкласс, который обрабатывает координации различных contentOffset
значения.
6 ответов
можно изменить смещение содержимого UIScrollView
без запуска обратного вызова делегата scrollViewDidScroll:
, установив границы UIScrollView
с исходным значением требуемого смещения содержимого.
CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
попробовать
id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;
работал для меня.
Как насчет использования существующих свойств UIScrollView?
if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
//your code
}
упрощая ответ @Tark, вы можете расположить scrollview без стрельбы scrollViewDidScroll
в одну строчку:
scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you'd like
другой подход-добавить некоторую логику в делегат scrollViewDidScroll, чтобы определить, было ли изменение смещения содержимого вызвано программно или касанием пользователя.
- добавьте логическую переменную 'isManualScroll' в свой класс.
- установите начальное значение false.
- в scrollViewWillBeginDragging установите значение true.
- в вашем scrollViewDidScroll проверьте, чтобы увидеть, что это правда, и только ответить, если это есть.
- в scrollViewDidEndDecelerating установите значение false.
- в scrollViewWillEndDragging добавьте логику, чтобы установить ее в false, если скорость равна 0 (поскольку scrollViewDidEndDecelerating не будет вызываться в этом случае).
это не прямой ответ на вопрос, но если вы получаете то, что кажется ложными такими сообщениями, это также может быть потому, что вы меняете границы. Я использую некоторый пример кода Apple с методом "tilePages", который удаляет и добавляет subview в scrollview. Это редко приводит к дополнительному scrollViewDidScroll: сообщения вызываются немедленно, поэтому вы попадаете в рекурсию, которую вы наверняка не ожидали. В моем случае я получил неприятный невозможно найти крушение.
то, что я в конечном итоге сделал, было очередью вызова в главной очереди:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(scrollView == yourScrollView) {
// dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
// The reason can be found here: http://stackoverflow.com/questions/9418311
dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
}
}