Отримайте UIScrollView, щоб прокрутити до вершини


Відповіді:


316

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

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

ОРИГІНАЛЬНИЙ

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

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

[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
    animated:YES];

50
Якщо ви робите це для iOS 7, можливо, вам доведеться враховувати UIScrollView contentInset, на жаль. [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];робить роботу для мене
runmad

11
Мені вдалося прокрутити верх, прямо під навігаційною панеллю та рядком стану. [scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];Він працює в iOS 6 і 7
Amozoss

Це не спрацювало для мене, ймовірно, тому, що я роблю щось божевільне із перевернутим виглядом у спрайт-наборі. Але якщо хто-небудь ще такий божевільний, як я, - а ваш список прокрутки за замовчуванням знаходиться внизу - це прокрутить його до верху:[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
GilesDMiddleton

Запізнілий коментар у день: слід налаштувати вміст вмісту, незалежно від версії ОС. iOS 7, як правило, використовує його для дозволу прокручування вмісту нижче рядка стану, але він завжди виявляється як властивість, тому його завжди хтось потенційно використовував.
Томмі

2
Що стосується iOS 11+, відповідь Якуба Труляра нижче за допомогою коригуваногоContentInset була корисною, принаймні в моєму випадку.
tnev

61

Ось розширення Swift, яке спрощує:

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

Використання:

myScrollView.scrollToTop()

40

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т.д.




17

Відповідь для 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

У iOS7 у мене виникли проблеми з отриманням певного прокрутки, щоб перейти до вершини, яка працювала в iOS6, і використовував це для встановлення прокрутки, щоб перейти до вершини.

[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];

У мене така сама проблема в iOS7. Хтось знає, як увімкнути це для UITableView?
DZenBot

1
Смішно, як це працює, коли анімація НІ, але не тоді, коли анімація ТАК. Якщо так, то вона прокручується майже до topdevgm16
Метт Бекер


2

Для повного тиражування поведінки рядка статусу scrollToTop нам потрібно не тільки встановити contentOffset, але й хочемо переконатися, що відображаються покажчики scrollIndicator. Інакше користувач може швидко загубитися.

Єдиний публічний метод досягти цього - це 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 або властивістю.


Я не тестував, але це має перенести це на наступний цикл, якщо ви просто використовуєте DISPATCH_TIME_NOW замість цього. Дякую за виконання цієї роботи, не впевнений, що мені це ще потрібно, але добре знати.
Дан Розенстарк

Минуло давно, і я не пам'ятаю точно, але я вважаю, що це не спрацювало. Віднесення до наступного циклу - це, як правило, перше, що я намагаюсь у таких випадках.
Ортвін Генц

2

Я думаю, що у мене є відповідь, яка повинна бути повністю сумісною з iOS 11, а також попередніми версіями (для вертикальної прокрутки)

При цьому береться до уваги нову adjustedContentInset , а також рахунки за додаткове зміщення потрібно , коли prefersLargeTitles включена на Панель навігації , яка , як видається , вимагає додаткового 52px зміщення поверх будь за замовчуванням

Це було трохи хитро, тому що customContentInset змінюється залежно від стану 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)
    }
}

Натхненний рішенням Якуба


2

Це дуже часто, коли панель навігації перекриває невелику частину вмісту scrollView, і схоже, що вміст починається не зверху. Для її виправлення я зробив 2 речі:

  • Інспектор розмірів - Перегляд прокрутки - Вміст вмісту -> Змінити з автоматичного на Ніколи.
  • Інспектор розмірів - Обмеження - "Вирівняти верхню частину до" (Верхні обмеження вирівнювання) - Другий пункт -> Змінити з Superview.Top на Safe Area.Top та значення (постійне поле) встановити на 0

Вставки вмісту - ніколи Вирівняйте ScrolView.Top до Safe Area.Top


1

Прокрутка до початку для UITableViewController, UICollectionViewControllerабо будь-якого UIViewControllerмаєUIScrollView

extension UIViewController {

  func scrollToTop(animated: Bool) {
    if let tv = self as? UITableViewController {
        tv.tableView.setContentOffset(CGPoint.zero, animated: animated)
    } else if let cv = self as? UICollectionViewController{
        cv.collectionView?.setContentOffset(CGPoint.zero, animated: animated)
    } else {
        for v in view.subviews {
            if let sv = v as? UIScrollView {
                sv.setContentOffset(CGPoint.zero, animated: animated)
            }
        }
    }
  }
}


-4

Я намагався всіма способами. Але мені нічого не вийшло. Нарешті мені це сподобалось.

Я додав self.view .addSubview(self.scroll)рядок коду у viewDidLoad. Після початку налаштування кадру для перегляду прокрутки та додавання компонентів до подання прокрутки.

Це працювало для мене.

Переконайтеся, що ви додали self.view .addSubview(self.scroll)рядок на початку. тоді ви можете додати елементи інтерфейсу.


Видаліть це. Хоча це, безумовно, мало сенс у той час, питання вашої ієрархії підрозділу не стосуються цього питання.
Дан Розенстарк

1
@ Cristik, якщо ваш перегляд прокрутки не знаходиться в ієрархії подання або ваш комп'ютер вимкнено, звичайно, нічого з цього не вийде. Але ОП запитала щось досить вузьке
Ден Розенстарк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.