Ottieni UIScrollView per scorrere verso l'alto


Risposte:


316

AGGIORNAMENTO PER iOS 7

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

ORIGINALE

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

o se si desidera preservare la posizione di scorrimento orizzontale e ripristinare la posizione verticale:

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

50
Se lo stai facendo per iOS 7, potresti dover tener conto UIScrollView contentInset, sfortunatamente. [self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];fa il lavoro per me
runmad

11
Sono stato in grado di scorrere verso l'alto, proprio sotto la barra di navigazione e di stato. [scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];Funziona su iOS 6 e 7
Amozoss,

Questo non ha funzionato per me, probabilmente perché sto facendo qualcosa di folle con una vista invertita nel kit sprite. Ma se qualcun altro è pazzo come me - e la tua vista di scorrimento è in fondo per impostazione predefinita - questo lo farà scorrere verso l'alto:[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
GilesDMiddleton

Commento di fine giornata: è necessario regolare l'inserzione del contenuto indipendentemente dalla versione del sistema operativo. iOS 7 sembra usarlo per consentire il contenuto di scorrimento sotto la barra di stato ma è sempre stato esposto come proprietà, quindi è sempre stato potenzialmente utilizzato da qualcuno.
Tommy,

2
Per iOS 11 e versioni successive, la risposta di Jakub Truhlář riportata di seguito utilizzando adjustedContentInset è stata utile, almeno nel mio caso.
tnev,

61

Ecco un'estensione Swift che semplifica:

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

Uso:

myScrollView.scrollToTop()

40

iOS 11 e versioni successive

prova a lavorare con il nuovo adjustedContentInset.

Ad esempio (scorrere verso l'alto):

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)

Anche se usi prefersLargeTitles, safe areaecc.



23

Uso setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];

17

Risposta per Swift 2.0 / 3.0 / 4.0 e iOS 7+:

let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)

8

In iOS7 ho avuto difficoltà a ottenere una particolare vista di scorrimento per andare in cima, che ha funzionato in iOS6, e ho usato questo per impostare la vista di scorrimento per andare in cima.

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

Ho lo stesso problema in iOS7. Qualcuno sa come abilitarlo per un UITableView?
DZenBot,

1
È divertente come funziona quando l'animazione è NO, ma non quando l'animazione è SÌ. Se SÌ, scorre quasi fino al topdevgm16
Matt Becker,


2

Per replicare completamente il comportamento scrollToTop della barra di stato, non solo dobbiamo impostare contentOffset, ma vogliamo anche assicurarci che vengano visualizzati gli Indicatori di scorrimento. Altrimenti l'utente può perdersi rapidamente.

L'unico metodo pubblico per raggiungere questo obiettivo è flashScrollIndicators. Sfortunatamente, chiamarlo una volta dopo aver impostato contentOffset non ha alcun effetto perché viene ripristinato immediatamente. Ho scoperto che funziona ogni volta che esegui il flash 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;
    });
}

Nel tuo UIScrollViewDelegate (o UITable / UICollectionViewDelegate) implementa questo:

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

Il ritardo di nascondere è un po 'più breve rispetto al comportamento scrollToTop della barra di stato, ma sembra comunque carino.

Si noti che sto abusando del tag di visualizzazione per comunicare lo stato "isScrollingToTop" perché ne ho bisogno attraverso i controller di visualizzazione. Se stai usando i tag per qualcos'altro, potresti volerlo sostituire con un iVar o una proprietà.


Non ho ancora testato, ma dovrebbe lanciarlo sul prossimo runloop se invece usi DISPATCH_TIME_NOW. Grazie per aver fatto questo lavoro, non sono sicuro di averne ancora bisogno, ma è buono a sapersi.
Dan Rosenstark,

È passato un po 'di tempo e non ricordo esattamente ma credo che non abbia funzionato. Il rinvio al prossimo runloop è in genere la prima cosa che provo in questi casi.
Ortwin Gentz,

2

Penso di avere una risposta che dovrebbe essere pienamente compatibile con iOS 11 e versioni precedenti (per scorrimento verticale)

Ciò tiene conto del nuovo adjustedContentInset e tiene conto anche dell'offset aggiuntivo richiesto quando si preferisce LargeTitles è abilitato sulla navigazione, che sembra richiedere un offset extra di 52px sopra qualunque sia l'impostazione predefinita

Questo è stato un po 'complicato perché la regolazione di AdjustContentInset varia in base allo stato titleBar (titolo grande vs titolo piccolo), quindi ho dovuto controllare e vedere qual era l'altezza del titleBar e non applicare l'offset 52px se è già nello stato grande. Impossibile trovare altri metodi per controllare lo stato della barra di navigazione, quindi se qualcuno ha un'opzione migliore rispetto a vedere se l'altezza è> 44,0 mi piacerebbe ascoltarlo

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)
    }
}

Ispirato dalla soluzione di Jakub


2

È molto comune quando la barra di navigazione si sovrappone alla piccola porzione del contenuto scrollView e sembra che il contenuto non inizi dall'alto. Per ripararlo ho fatto 2 cose:

  • Controllo dimensioni - Scorri vista - Inserimenti contenuti -> Cambia da Automatico a Mai.
  • Ispettore dimensioni - Vincoli- "Allinea in alto a" (Vincoli di allineamento in alto) - Secondo elemento -> Passa da Supervision.Top a Safe Area.Top e il valore (campo costante) impostato su 0

Inserimenti di contenuti - Mai Allinea ScrolView. Vai su Area sicura


1

Rotolo alla parte superiore per UITableViewController, UICollectionViewControllero UIViewControlleraventiUIScrollView

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)
            }
        }
    }
  }
}

0

In SWIFT 5 Basta impostare Content Offset su zero

scrollView.setContentOffset(CGPoint.zero, animated: true)

-4

Ho provato in tutti i modi. Ma niente ha funzionato per me. Alla fine mi è piaciuto.

Ho aggiunto la self.view .addSubview(self.scroll)riga di codice in viewDidLoad. Dopo aver iniziato a configurare la cornice per la vista di scorrimento e i componenti aggiunti alla vista di scorrimento.

Ha funzionato per me.

Assicurati di aver aggiunto la self.view .addSubview(self.scroll)riga all'inizio. quindi è possibile aggiungere elementi dell'interfaccia utente.


Si prega di eliminare questo. Anche se sicuramente aveva senso in quel momento, i problemi della gerarchia delle sottoview non sono rilevanti per questa domanda.
Dan Rosenstark,

1
@Cristik se la vista di scorrimento non è nella gerarchia della vista o il computer è spento, ovviamente nulla di tutto ciò funzionerà. Ma l'OP ha chiesto qualcosa di piuttosto stretto
Dan Rosenstark, il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.