Получите UIScrollView, чтобы прокрутить к вершине - PullRequest
158 голосов
/ 26 февраля 2012

Как сделать прокрутку UIScrollView наверх?

Ответы [ 13 ]

306 голосов
/ 26 февраля 2012

ОБНОВЛЕНИЕ ДЛЯ iOS 7

[self.scrollView setContentOffset:
    CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];

ORIGINAL

[self.scrollView setContentOffset:CGPointZero animated:YES];

или если вы хотите сохранить положение горизонтальной прокрутки и просто сбросить положение по вертикали:

[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
    animated:YES];
51 голосов
/ 01 февраля 2016

Вот расширение Swift, которое облегчает его:

extension UIScrollView {
    func scrollToTop() {
        let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
        setContentOffset(desiredOffset, animated: true)
   }
}

Использование:

myScrollView.scrollToTop()
30 голосов
/ 07 октября 2017

iOS 11 и выше

попробуйте поработать с новым adjustedContentInset.

Например (прокрутите вверх):

var offset = CGPoint(
    x: -scrollView.contentInset.left, 
    y: -scrollView.contentInset.top)

if #available(iOS 11.0, *) {
    offset = CGPoint(
        x: -scrollView.adjustedContentInset.left, 
        y: -scrollView.adjustedContentInset.top)    
}

scrollView.setContentOffset(offset, animated: true)

Даже если вы используете prefersLargeTitles, safe area и т. Д.

26 голосов
/ 12 февраля 2018

для Swift 4

scrollView.setContentOffset(.zero, animated: true)
22 голосов
/ 26 февраля 2012

Использование setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];
16 голосов
/ 09 января 2016

Ответ для Swift 2.0 / 3.0 / 4.0 и iOS 7 +:

let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)
8 голосов
/ 23 сентября 2013

В iOS7 у меня были проблемы с получением определенного вида прокрутки для перехода наверх, который работал в iOS6, и использовал его, чтобы настроить вид прокрутки для перехода наверх.

[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
4 голосов
/ 01 ноября 2016

Swift 3.0.1 версия ответ Роба Майоффа :

self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
2 голосов
/ 20 мая 2014

Чтобы полностью воспроизвести поведение строки состояния scrollToTop, нам нужно не только установить contentOffset, но и убедиться, что отображаются scrollIndicators.В противном случае пользователь может быстро потеряться.

Единственный публичный способ сделать это - flashScrollIndicators.К сожалению, вызов его один раз после установки contentOffset не имеет никакого эффекта, потому что он сбрасывается немедленно.Я обнаружил, что это работает, когда выполняется флэш-память каждый раз в scrollViewDidScroll:.

// define arbitrary tag number in a global constants or in the .pch file
#define SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG 19291

- (void)scrollContentToTop {
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];

    self.scrollView.tag = SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.scrollView.tag = 0;
    });
}

В вашем UIScrollViewDelegate (или UITable / UICollectionViewDelegate) реализуйте это:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
        [scrollView flashScrollIndicators];
    }
}

Задержка скрытия являетсянемного короче по сравнению с поведением scrollToTop строки состояния, но все равно выглядит красиво.

Обратите внимание, что я злоупотребляю тегом представления для передачи состояния "isScrollingToTop", потому что мне это нужно через контроллеры представления.Если вы используете теги для чего-то другого, вы можете заменить это на iVar или свойство.

1 голос
/ 08 мая 2018

Мне кажется, у меня есть ответ, который должен быть полностью совместим с iOS 11, а также с предыдущими версиями (для вертикальной прокрутки)

Это учитывает новый СкорректированныйContentInset , а также учитывает дополнительное смещение, требуемое, когда prefersLargeTitles включено на навигационной панели, которая, по-видимому, требует дополнительного 52-пиксельного смещения поверх любого значения. по умолчанию

Это было немного сложно, потому чтоsetContentInset изменяется в зависимости от состояния titleBar (большой заголовок против маленького заголовка), поэтому мне нужно было проверить и посмотреть, какова была высота titleBar, и не применять смещение 52px, если оно уже находится в большом состоянии. Не удалось найти какой-либо другой метод для проверки состояния навигационной панели, поэтому, если у кого-то есть лучший вариант, чем видеть, является ли высота> 44,0, я бы хотел услышать его

func scrollToTop(_ scrollView: UIScrollView, animated: Bool = true) {
    if #available(iOS 11.0, *) {
        let expandedBar = (navigationController?.navigationBar.frame.height ?? 64.0 > 44.0)
        let largeTitles = (navigationController?.navigationBar.prefersLargeTitles) ?? false
        let offset: CGFloat = (largeTitles && !expandedBar) ? 52: 0
        scrollView.setContentOffset(CGPoint(x: 0, y: -(scrollView.adjustedContentInset.top + offset)), animated: animated)
    } else {
        scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: animated)
    }
}

Вдохновленный решением Якуба

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...