UIScrollView non scorre


128

Ho una UIScrollViewche contiene molti UIImageViews, UILabels, ecc ... le etichette sono molto più lunghe della UIScrollView, ma quando eseguo l'app, non posso fare clic e scorrere verso il basso ...

Perché potrebbe essere?

Grazie


Nuovo 2013/03/26 mi sono imbattuto in un modo più semplice per fare questo senza codice (impostazione contentSize) stackoverflow.com/a/15649607/1705353
Dickey Singh

Risposte:


169

È sempre utile mostrare uno snippet di codice di lavoro completo:

// in viewDidLoad (if using Autolayout check note below):

UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set

[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size

Swift 4.0

let myScrollView
let contentView

// scrollview won't scroll unless content size explicitly set

myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size //sets ScrollView content size

Non ho trovato un modo per impostare contentSize in IB (a partire da Xcode 5.0) .

Nota: se si utilizza Autolayout, il posto migliore per inserire questo codice è all'interno del -(void)viewDidLayoutSubviewsmetodo.


12
Non dimenticare di impostare myScrollView.delegate = selfANCHE, se continua a non funzionare, la risposta di seguito ha un GRANDE consiglio (vai su xib / StoryBoard e assicurati che "AutoLayout" sia disabilitato). Suggerimento: puoi anche includere <UIScrollViewDelegate>nel tuo file .h se vuoi fare cose come scorrere programmaticamente UIScrollView.
Albert Renshaw,

1
@AlbertRenshaw avresti dovuto aggiungere una risposta così avrei potuto darti un +1 :) AutoLayout era il problema con me .... mi ha fatto impazzire per circa 4 ore.
logixologo,

2
Inserire il codice viewDidLayoutSubviewsha funzionato per me.
Amr Lotfy,

Per me il problema era che non aveva bisogno di scorrere, poiché tutto si adattava allo schermo.
Daniel Springer

122

Se non riesci a scorrere la vista anche dopo aver impostato contentSize correttamente, assicurati di deselezionare "Usa AutoLayout" in Interface Builder -> File Inspector.


164
In alternativa, puoi impostare contentSize in viewDidLayoutSubviews: e verrà applicato dopo il completamento del completamento automatico.
Chris Vasselli,

2
@ "Chris Vasselli" risolve il mio problema .. GR8 .. :-)
Ayaz

3
Il commento di Chris dovrebbe essere una risposta separata!
ninjaneer,

1
Grazie mille Chris Vasselli! Con Auto Layout abilitato, non funzionerà in viewDidLoad ma funziona con viewDidLayoutSubviews!
Romain,

1
Woah, non ho mai notato tutti questi commenti prima! Sono contento di aver potuto aiutare così tanti di voi! Ho appena pubblicato una risposta separata, quindi spero che sia più facile da trovare.
Chris Vasselli,

68

Devi impostare il contentSize proprietà della vista di scorrimento affinché scorra correttamente.

Se stai usando layout automatico, è necessario impostare contentSizein viewDidLayoutSubviewsin modo che esso da applicare dopo il completamento del layout automatico.

Il codice potrebbe apparire così:

-(void)viewDidLayoutSubviews
{
    // The scrollview needs to know the content size for it to work correctly
    self.scrollView.contentSize = CGSizeMake(
        self.scrollContent.frame.size.width,
        self.scrollContent.frame.size.height + 300
    );
}

Grazie una tonnellata .. Questo ha funzionato perché per qualche motivo, anche quando ho impostato il valore della contentSizedimensione di contentView, la dimensione di scrollView e contentView sembra essere impostata allo stesso modo. Ma impostando l'altezza di contentSizeun valore maggiore dell'altezza di contentView, ha funzionato.
Skywalker,

viewDidLayoutSubviewspuò essere chiamato più volte durante un ciclo di vita in modo da correre il rischio aumentando l'altezza più grande del previsto.
anon_nerd,

@anon_nerd controlla solo se è già stato chiamato e aggiungi l'altezza in caso contrario
Daniel Springer

45

La risposta sopra è corretta: per consentire lo scorrimento, è necessario impostare le dimensioni del contenuto.

Se stai usando il builder di interfacce un modo pulito per farlo è con gli attributi di runtime definiti dall'utente. Per esempio:

inserisci qui la descrizione dell'immagine


questo non ha fatto nulla per me.
coolcool1994,

4
Spiacenti, la foto mostra {0, 0}, ma ovviamente devi inserire numeri abbastanza grandi. . questo approccio funziona solo per visualizzazioni semplici in cui si conosce la dimensione del contenuto in anticipo. . . (in effetti, per viste complesse raccomando comunque codice puro).
Jasper Blues,

Molto meno confuso che farlo programmaticamente. Grazie!
Jake Stoeffler,

1
@JakeStoeffler welcome! :) Quando utilizzo IB, mi piace mantenere tutta la configurazione lì (non frammentata). Ma quando le cose diventano complesse (widget di vista riutilizzabili; adattatori di modelli, manipolazioni di livelli; CAAnimations, ecc.) Preferisco le viste completamente programmatiche. . . più fluente.
Jasper Blues

Ho provato questo, funziona quando appare la vista, ma al cambio di orientamento, il contentSize definito nella schermata sopra è ignorato e il mio registro dice che contentSize è impostato su 0,0. Qualche idea su come risolverlo?
Shoogle,

40

Prova a ridimensionare la dimensione del contenuto a numeri enormi. Non riesco a capire perché la mia vista di scorrimento non scorra anche quando la sua dimensione del contenuto sembra essere maggiore della dimensione del controllo. Ho scoperto che se la dimensione del contenuto è inferiore al necessario, non funziona anche.

self.scrollView.contentSize = CGSizeMake(2000, 2000);

Invece del 2000 puoi mettere i tuoi grandi numeri. E se funziona, significa che la dimensione del contenuto non è abbastanza grande quando si ridimensiona.

Il delegato non è necessario per il funzionamento della vista di scorrimento.


2
Genius - un modo così semplice per controllare cosa sta succedendo. Grazie mille!
The Crazy Chimp

13

Assicurati di avere la proprietà contentSize della vista di scorrimento impostata sulla dimensione corretta (ovvero una abbastanza grande da includere tutto il tuo contenuto).


1
devo farlo programmaticamente? o posso farlo in IB?
Segna

Se stai usando IB, puoi impostarlo da lì - vedi sotto. . (Risposta separata, quindi posso includere foto).
Jasper Blues,

7

Deseleziona "Usa autolayout" per me.

Ambiente: xCode 5.0.2 Storyboard ios7


5

Nel mio caso ho dovuto impostare delaysContentTouchessu true perché gli oggetti all'interno di scrollView stavano tutti catturando gli eventi di tocco e gestendoli invece di lasciare che lo stesso scrollView lo gestisse.


Ho lo stesso problema. Il problema per me è che trasformando i ritardiContentTouches su true, finirai con disegni di qualità inferiore con una matita di mele. Ma questo è un caso limite :) nella maggior parte dei casi risolve il problema
RomOne,

4

Set contentSizedi proprietà di UIScrollviewin ViewDidLayoutSubviewsmetodo. Qualcosa come questo

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}

3

L'idea del perché la vista di scorrimento non scorre perché imposti una dimensione del contenuto per lo scorrimento inferiore alla dimensione della vista di scorrimento, il che è sbagliato. È necessario impostare una dimensione del contenuto maggiore della dimensione della vista di scorrimento per spostarsi durante lo scorrimento.

La stessa idea con lo zoom, si imposta il valore minimo e massimo per lo zoom che verrà applicato tramite l'azione di zoom.

benvenuto :)


3

Una piccola aggiunta, tutti sopra sono i veri motivi per cui la vista di scorrimento potrebbe non scorrere, ma a volte senza ragione questo potrebbe essere il motivo specialmente quando la vista di scorrimento viene aggiunta tramite codice e non IB, potresti aver aggiunto le tue viste secondarie alla vista padre e non la vista di scorrimento questo fa sì che la vista secondaria non scorra

e mantieni la dimensione del contenuto impostata e più grande del frame della vista padre (duhh !!)


3

L'ho fatto funzionare al mio primo tentativo. Con layout automatico e tutto, nessun codice aggiuntivo. Quindi una visualizzazione della raccolta è diventata banana, si è arrestata in modo anomalo in fase di esecuzione, non riuscivo a trovare ciò che non andava, quindi l'ho eliminata e ricreata (sto usando Xcode 10 Beta 4. Sembrava un bug) e quindi lo scorrimento era scomparso. La vista Collezione ha funzionato di nuovo, però!

Molte ore dopo .. questo è ciò che mi ha risolto. Ho avuto il seguente layout:

UIView

  • Area sicura
  • Scorri la vista
    • Vista contenuto

È tutto nei vincoli. L'area di sicurezza viene definita automaticamente dal sistema. Nel peggiore dei casi rimuovere tutti i vincoli per le visualizzazioni di scorrimento e del contenuto e non avere il ripristino / creazione di IB per te. Rendili manualmente, funziona.

  • Per la vista Scorrimento ho fatto: Allinea il Trailing / In alto all'Area sicura. Pari larghezza / altezza all'area sicura .
  • Per la vista Contenuto ho fatto: Allinea Trailing / Leading / In alto / In basso a Superview (la vista di scorrimento)

fondamentalmente l'idea è quella di avere la vista Contenuto adatta a Scrollview, che si adatta all'Area Sicura.

Ma come tale non ha funzionato. La visualizzazione contenuto non ha raggiunto l'altezza. Ho provato tutto il possibile e l'unico a fare il trucco è stato l' altezza della vista Contenuto creata tenendo sotto controllo la vista Contenuto ... su se stessa . Ciò ha definito un'altezza fissa, il cui valore è stato calcolato dalle dimensioni del controller della vista (definito come forma libera, più lungo del display reale, per contenere tutte le mie visualizzazioni secondarie) e alla fine ha funzionato di nuovo!


Di niente! So esattamente come ti sei sentito .. ;-)
Michele Dall'Agata,

Thaaaaks, ho trascorso molte ore e questo ha risolto il mio problema
Andoni Da Silva,

3

se ricevi un messaggio (IOS8 / swift) che viewDidLayoutSubviewsnon esiste, usa invece quanto segue

override func viewDidAppear(animated: Bool)

Questo mi ha risolto


2

Qualcosa che non è stato menzionato prima!

Assicurati che la tua presa sia correttamente collegata a scrollView! Dovrebbe avere un cerchio pieno, ma anche se hai un cerchio pieno, scrollView potrebbe non essere collegato, quindi ricontrolla! Passa il mouse sopra il cerchio e vedi se viene evidenziata la vista di scorrimento effettiva! (Questo è stato un caso per me)

//Connect below well to the scrollView in the storyBoard
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

2

Spesso il codice è corretto se hai seguito un tutorial ma ciò che molti principianti non sanno è che scrollView NON scorrerà normalmente attraverso il simulatore. Si supponga di scorrere solo quando si preme verso il basso sul tappetino per mouse e contemporaneamente si scorre. Molti esperto / utenti XCode Swift / Obj-C sono così utilizzare per fare questo e quindi non sanno come potrebbe eventualmente essere trascurato dai principianti. Ciao :-)

@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(scrollView)
    // Do any additional setup after the view
}

override func viewWillLayoutSubviews(){
    super.viewWillLayoutSubviews()
    scrollView.contentSize = CGSize(width: 375, height: 800)
}

Questo codice funzionerà perfettamente finché fai quello che ho detto sopra


1

Se nessuna delle altre soluzioni funziona per te, verifica che la vista di scorrimento sia effettivamente UIScrollViewin Interface Builder.

Ad un certo punto negli ultimi giorni, il mio UIScrollView tipo è cambiato spontaneamente in a UIView, anche se la sua classe diceva UIScrollViewnell'ispettore. sto usandoXcode 5.1 (5B130a) .

Puoi creare una nuova vista di scorrimento e copiare misure, impostazioni e vincoli dalla vista precedente oppure puoi modificare manualmente la vista in a UIScrollViewnel xibfile. Ho fatto un confronto e ho trovato le seguenti differenze:

Originale:

<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>

Dopo che il tipo è cambiato spontaneamente:

<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>

Quindi ho sostituito la <view>linea con la mia <scrollView>linea originale .

Ho anche sostituito il tag di chiusura della vista </view>con </scrollView>.

Assicurati di mantenere l'id uguale alla vista corrente, in questo caso: id = "qRn-TP-cXd".

Ho anche dovuto svuotare lo xib dalla cache di Xcode eliminando i dati derivati ​​dall'app:

  • Xcode->Window->Organizer->Projects, scegli il tuo progetto, nella riga Dati derivati, fai clic su Elimina ...

O se si utilizza un dispositivo:

  • Xcode->Window->Organizer->Device, scegli il tuo dispositivo-> Applicazioni, scegli la tua app, fai clic su (-)

Ora pulisci il progetto e rimuovi l'app dal simulatore / dispositivo:

  • Xcode->Product->Clean
  • iOS Simulator/device->presse tieni premuto il tasto app->click(X) per rimuoverlo

Dovresti quindi essere in grado di creare ed eseguire la tua app e avere di nuovo funzionalità di scorrimento.

PS Non ho dovuto impostare la dimensione del contenuto della vista di scorrimento viewDidLayoutSubviews o disattivare il layout automatico, ma YMMV.


1

Se la tua scrollViewè una sottoview di un containerViewtipo, assicurati che scrollViewsia all'interno della cornice o dei limiti di containerView. Avevo containerView.clipsToBounds = NOancora permesso di vedere scrollView, ma perché scrollViewnon rientrava nei limiti dicontainerView non avrebbe rilevato gli eventi di tocco.

Per esempio:

containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;

Sarai in grado di vedere scrollView ma non riceverà le interazioni dell'utente.


1

aggiungendo il seguente codice ha viewDidLayoutSubviewsfunzionato per me con Autolayout. Dopo aver provato tutte le risposte:

- (void)viewDidLayoutSubviews
{
    self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);

}

//set the height of content size as required

1

Aggiungi il UIScrollViewDelegatee aggiungendo il seguente codice al viewDidAppearmetodo risolto per me.

@interface testScrollViewController () <UIScrollViewDelegate>

-(void)viewDidAppear:(BOOL)animated {
    self.scrollView.delegate = self;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.contentSize = CGSizeMake(375, 800);
}

1

Il mio problema è stato risolto da:

  1. impostazione del contenuto Dimensione su scrollView su una grande altezza
  2. MA anche io ho dovuto correggere i vincoli superiore e / o inferiore delle viste all'interno di scrollView, il che significava che gli indicatori di scorrimento venivano visualizzati sullo schermo ma il contenuto non scorreva

Una volta rimossi i vincoli superiore e / o inferiore associati all'area sicura e / o alla superview, le viste all'interno di scrollView potevano scorrere di nuovo e non rimanevano fisse nella parte superiore della parte inferiore dello schermo!

Spero che questo fermi qualcun altro dalle ore di dolore con questo particolare problema.


1

l'ennesimo caso divertente:

scrollview.superview.userInteractionEnabled deve essere vero

Ho sprecato 2 + ore a inseguire questo solo per capire che il genitore è UIImageView che, naturalmente, ha userInteractionEnabled == false


0

Dopo aver fallito con le risposte fornite in questo thread, mi sono imbattuto in questo articolo con la soluzione.

Esistono due cose non intuitive sull'impostazione della vista di scorrimento con autolayout:

  1. I vincoli impostati come margine tra la visualizzazione contenuto e la visualizzazione scorrimento non influenzano la dimensione della visualizzazione contenuto. Sono davvero dei margini. E per farlo funzionare, la visualizzazione contenuto dovrebbe avere una dimensione fissa.
  2. Il trucco della dimensione fissa è che puoi impostare la larghezza della visualizzazione contenuto uguale a quella del genitore della vista scorrimento. Basta selezionare entrambe le viste nella struttura a sinistra e aggiungere il vincolo di uguale larghezza.

Questa è la sostanza di quell'articolo. Per una spiegazione completa, comprese le illustrazioni, dai un'occhiata.


@PredragManojlovic Come può essere più generale di così? Questo è l'unico modo in cui ho potuto far funzionare correttamente la vista di scorrimento, usando il layout automatico.
H. de Jonge,

0

Ho scoperto che con questo problema di AutoLayout ... se faccio solo l' ViewControlleruso UIViewinvece che UIScrollViewper la classe ... quindi aggiungo un UIScrollViewme stesso ... che funzioni.


0

Ho avuto lo stesso problema in IB.

Dopo aver impostato la parte iniziale, finale, superiore e inferiore di scrollView su superView. Ho apportato le seguenti modifiche per rendere scorrevole il containerView, che ha funzionato.

Per far scorrere scrollView solo in direzione orizzontale, creare il vincolo con centerY di scrollViewY = CenterY di ContainerView

e per renderlo scorrevole verticalmente, fai centroX di scrollView = centerX di ContainerView

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.