Come disabilitare lo scorrimento orizzontale di UIScrollView?


92

Ho un UIViewtrampolino di lancio come iPhone. L'ho creato usando un UIScrollViewand UIButtons. Voglio disabilitare lo scorrimento orizzontale su detto scrollview. Voglio solo lo scorrimento verticale. Come ci riesco?


5
Dovresti cambiare il titolo: chiedi orizzontale nella domanda e verticale nel titolo. Le persone trovano le tue domande più tardi sui motori di ricerca, quindi è ancora importante 2 anni dopo :)
Julien

@RahulVyas L'uomo sopra ha ragione. La modifica del titolo ridurrà la confusione per i principianti che arrivano qui tramite un motore di ricerca (come me;)).
SpacyRicochet

Ho modificato il titolo per conto del poster. (Anche se è attualmente in attesa di revisione tra pari prima che la modifica sia visibile.)
Duncan Babbage

Risposte:


125

Devi impostare la contentSizeproprietà del file UIScrollView. Ad esempio, se il tuo UIScrollViewè largo 320 pixel (la larghezza dello schermo), puoi farlo:

CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];

Il UIScrollViewsarà quindi scorrere solo verticalmente, perché può già visualizzare tutto in orizzontale.


6
Ciao. Questa soluzione funziona davvero bene! Grazie per quello. Ho provato a impostare la larghezza statica su 0. Anche per me funziona. Non so se potrebbero esserci degli effetti collaterali in seguito. Ma se non si conosce la dimensione (cioè il codice universale per iPhone e iPad) funziona benissimo!
JackPearse

5
Penso che sia meglio fare CGSizeMake (0, myScrollableHeight), quindi lo scorrimento orizzontale è disabilitato anche se non sono state mostrate tutte le sottoview.
LightNight

NB Impostando una delle dimensioni su 0 quando si utilizza il paging, VoiceOver annuncerà il numero di pagina come "pagina 1 di 1" indipendentemente dal valore corretto
josef

1
Invece di passare la larghezza come 320 hardcoded, possiamo passare come: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit kumar

90

AGGIORNATO: (Dopo che @EranMarom ha sottolineato il suo commento)

È possibile interrompere lo scorrimento orizzontale o verticale nel ScrollViewDelegateMetodo. Ecco come

Arresta lo scorrimento orizzontale:

Se vuoi scorrere orizzontalmente, devi aumentare il contentOffset.x. Impedendo che si arresti lo scrollview scorre in direzione orizzontale.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.x = 0.0
}

Arresta lo scorrimento verticale:

Se vuoi scorrere verticalmente, devi aumentare il contentOffset.y. Impedendo che si arresti lo scrollview scorrere in direzione verticale.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.y = 0.0
}

Il codice precedente impedisce le modifiche in xe ydi a scrollview contentOffsete porta a interrompere lo scorrimento in scrollViewDidScroll:metodo.


1
Sto prendendo in considerazione il downvoting perché questa risposta non spiega che hai appena dato il codice e basta. Una risposta del genere non è molto buona. La buona risposta si spiega da soli, mentre gli sviluppatori esperti potrebbero capire che questo nuovo sviluppatore potrebbe non capire cosa sta succedendo qui. Non ancora downvoted perché dà la possibilità di migliorare.
Popeye

13
Questa è una specie di hack, ma ha funzionato quando tutto il resto ha fallito. Quindi +1, ma usa solo come ultima risorsa.
i_am_jorf

5
Uso anche questo metodo delegato, ma sostituisco il corpo con una riga singola, ad esempio: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);per disabilitare lo scorrimento orizzontale. Lo trovo più leggibile, è più piccolo e non ha senso fare il test per zero perché non c'è praticamente alcun sovraccarico con il codice che lo esegue raramente (cioè poche decine di volte al secondo al massimo).
Echelon

perché stai cambiando il contentOffset dopo "didscroll", non come prima di 'willscroll', e questa è una soluzione a martello, ma io stesso non ho votato in negativo, perché 18 voti positivi e la risposta è 75, quindi non è degno di voto negativo
LolaRun

2
Ancora più semplice, utilizzare scrollView.contentOffset.y = 0.0per interrompere lo scorrimento verticale e scrollView.contentOffset.x = 0.0per interrompere lo scorrimento orizzontale, nella scrollViewDidScroll()funzione delegato. Tuttavia, credo che assicurarsi che sia scrollView.contentSizeuguale a scrollView.frame.sizesia una soluzione migliore (corretta). Vedi la risposta di @danbeaulieu.
emem

11

dall'uso di iOS7

self.automaticallyAdjustsScrollViewInsets = NO;

// e crea il tuo scroller di pagine con 3 pagine

    self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
    [self.pageView setShowsVerticalScrollIndicator:NO];
    [self.pageView setPagingEnabled:YES];
    [self.view addSubview:self.pageView];

Non penso che questo disabiliterà il comportamento di scorrimento di una scrollview. È??
Dinesh Raja

self.collectionView.pagingEnabled = YES;mi ha aiutato a risolvere il problema con lo scorrimento fluido (non il trascinamento). Il problema era nel metodo scrollViewWillEndDragging:: targetContentOffset era lo stesso di scrollView.contentOffset e la logica di rilevamento della pagina non funziona correttamente.
sig

11

Soluzione rapida

Crea due punti vendita, uno per la tua visualizzazione e uno per la visualizzazione a scorrimento:

@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!

Quindi nel tuo viewDidLayoutSubviews puoi aggiungere il seguente codice:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: myView.frame.size.height)
scrollView.contentSize = scrollSize

Quello che abbiamo fatto è raccogliere l'altezza e la larghezza della visualizzazione e impostare la dimensione del contenuto scrollViews in modo che corrisponda. Ciò interromperà lo scorrimento orizzontale della visualizzazione a scorrimento.


Altri pensieri:

CGSizeMake prende una larghezza e un'altezza usando CGFloats. Potrebbe essere necessario utilizzare l'altezza esistente di UIScrollViews per il secondo parametro. Che sarebbe simile a questo:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)

E se non conosci l'altezza o la larghezza (dispositivo universale)? @danbeaulieu
Lukesivi

@lukesIvi "myView.frame.width" estrae dinamicamente la larghezza dall'IBOutlet "myView".
Dan Beaulieu

4

Nel mio caso, con Swift 4.2 puoi usare:

Disabilita lo scorrimento verticale:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = 0.0
}

Disabilita lo scorrimento orizzontale:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}

3

Puoi selezionare la vista, quindi Attributes Inspectordeseleziona User Interaction Enabled.


3

Nel mio caso la larghezza del contentView era maggiore della larghezza di UIScrollView e questo era il motivo dello scorrimento orizzontale indesiderato. L'ho risolto impostando la larghezza di contentView uguale alla larghezza di UIScrollView.

Spero che aiuti qualcuno


@Nostradamus felice di aiutare
Gulfam Khan

0

Avevo il contentInset tableview impostato in viewDidLoad (come sotto) che cosa causa lo scorrimento orizzontale

self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);

Verificare se sono presenti contenuti di visualizzazione tabella impostati per diversi motivi e disabilitarli


0

Ho lottato con questo per un po 'di tempo provando senza successo i vari suggerimenti in questo e in altri thread.

Tuttavia, in un altro thread (non so dove) qualcuno ha suggerito che l'utilizzo di un vincolo negativo su UIScrollView ha funzionato per lui.

Quindi ho provato varie combinazioni di vincoli con risultati incoerenti. Quello che alla fine ha funzionato per me è stato aggiungere i vincoli iniziali e finali di -32 alla scrollview e aggiungere una textview (invisibile) con una larghezza di 320 (e centrata).


0

Prova questo:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];

0

Disabilita lo scorrimento orizzontale sovrascrivendo la contentOffsetproprietà nella sottoclasse.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}

0

Introdotta in iOS 11 è una nuova proprietà su UIScrollView

var contentLayoutGuide: UILayoutGuide

La documentazione afferma che:

Utilizzare questa guida al layout quando si desidera creare vincoli di layout automatico relativi all'area del contenuto di una visualizzazione a scorrimento.

Insieme a qualsiasi altro vincolo di layout automatico che potresti aggiungere, vorrai vincolare il numero widthAnchordegli UIScrollView"s" contentLayoutGuidealla stessa dimensione del "frame". Puoi utilizzare il frameLayoutGuide(introdotto anche in iOS 11) o qualsiasi larghezza esterna (come la tua superView).

esempio:

NSLayoutConstraint.activate([
  scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])

Documentazione: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide


-1

Una volta che l'ho fatto sostituendo UIScrollView con un UITableView con solo 1 cella, ha funzionato bene.


1
Spiacenti, questo non risponde alla domanda.
David

-1

Usa questa singola riga.

self.automaticallyAdjustsScrollViewInsets = NO;

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.