Come posso utilizzare Autolayout per impostare i vincoli sul mio UIScrollview?


176

Ho trascorso due giorni a provare le varie soluzioni per gli approcci di Autolayout misti e puri per ottenere quella che era una banale configurazione scrollview prima del autolayout, ed è ora ufficiale - devo essere troppo stupido. Lo sto configurando principalmente in Storyboard (beh, è ​​così).

Quindi ecco la mia richiesta di aiuto.

viewtree:

UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton

I pulsanti dovrebbero scorrere in orizzontale (da sinistra a destra e viceversa). Può qualcuno si prega di farmi sapere come impostare i vincoli per raggiungere questo obiettivo utilizzando puro Autolayout ???

-

Ho provato l'approccio misto, in questo modo:

UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton

... e l'impostazione di vincoli di larghezza e altezza fissi per contentviewe le translatesAutoresizingMaskIntoConstraintsimpostazioni secondo il TechNote di Apple. I pulsanti e la vista di scorrimento vengono impostati mediante vincoli. Questo fa scorrere lo scrollview (yay) ma ahimè, scorre troppo lontano! Per quanto ne so, l'ampiezza dello scorrimento è in qualche modo raddoppiata rispetto a come ho impostato la visualizzazione del contenuto su ??? !!! ???

Ho provato anche il puro approccio di autolayout, sia con contentviewche senza. Tutte le visualizzazioni sono translatesAutoresizingMaskIntoConstraints=NO, tranne per self.view. I pulsanti hanno vincoli di larghezza / altezza fissi e sono bloccati su tutti e quattro i bordi della vista di scorrimento. Non scorre nulla.

Quindi sono totalmente sconcertato perché non riesco a farlo funzionare correttamente. Qualsiasi aiuto è molto apprezzato e se hai bisogno di altre informazioni, chiedi!

Schermata AGGIORNATA con soluzione - vincoli buttonZ:

inserisci qui la descrizione dell'immagine

EDIT @ Jamie Forrest Quindi la soluzione risulta essere il vincolo finale errato sull'ultimo pulsante. Invece di 6441, il valore che avevo impostato era negativo, -6441. La cosa difficile è che quando si imposta il valore nello storyboard, ci sono due opzioni nella barra degli strumenti Pin:

inserisci qui la descrizione dell'immagine

Il valore di tela corrente è negativo (senza scorrimento) e l'opzione di seguito è positiva (attivazione scorrimento). Questo significa che non sono stupido ma almeno mezzo cieco credo. Anche se, per mia difesa, non è in qualche modo inquietante che XCode non mostri un errore per l'impostazione "errata"?

MODIFICATO ANCORA Ora è divertente ... cambiare il valore finale da -6441 (no scroll) a 6441 abilitato scroll. Ma il mio vecchio amico "troppo contenuto" era tornato, portando a una dimensione del contenuto doppia rispetto a come dovrebbe essere! La soluzione per ottenere lo scorrimento del contenuto corretto era impostare il vincolo finale su ZERO! Questo non è ovvio quando si lavora in Storyboard ma guardando il codice di @Infinity James, è come dovrebbe essere.


Dove si calcola / imposta la dimensione del contenuto per la vista di scorrimento? Facendo riferimento al tuo primo tentativo usando contentView e hai detto che scorre troppo lontano.
Tim

2
Per quanto ne so, non è possibile impostare contentSizeun UIScrollViewutilizzando solo il layout automatico. Ed è quello contentSizeche definisce quanto puoi scorrere. Quindi dovrai impostarlo manualmente da qualche parte alla fine. Per il resto, è possibile utilizzare i vincoli di layout per impostare i frame della vista l'uno rispetto all'altro.
Guillaume,

@Jeff, la dimensione del contenuto è fissa, non cambia mai. Ho impostato la dimensione del contenuto nello storyboard inserendo manualmente l'altezza e la larghezza corrette per la vista contenuti e aggiungo l'altezza e la larghezza con vincoli nello storyboard.
user1459524

Stampa i tuoi contenuti Dimensione in fase di esecuzione, controlla se corrisponde ai valori che hai inserito. ContentSize determina la quantità di scorrimento che si verifica, quindi il problema con il primo tentativo è relativo a contentSize.
Tim

@Guillaume, quindi l'approccio del "puro autolayout" non è poi così puro? Ma COME imposto manualmente contentSize? Come accennato in precedenza, sto impostando l'altezza / larghezza della vista del contenuto a valori fissi (nello storyboard). Ma scorre troppo lontano (2x).
user1459524

Risposte:


68

È difficile vedere i valori esatti e l'impostazione dei tuoi vincoli quando li hai incollati qui, quindi non sono sicuro di guardare i tuoi screenshot in cui hai sbagliato.

Al posto di una spiegazione di cosa non va nella tua configurazione, ho creato un progetto di esempio di base con una gerarchia di vista molto simile e un'impostazione dei vincoli a quella che descrivi. Lo scorrimento orizzontale funziona come previsto nel progetto di esempio, che utilizza l'approccio "Pure AutoLayout" descritto da Apple nella Nota tecnica .

Inizialmente avevo anche molti problemi a far funzionare Auto Layout UIScrollView. La chiave per farlo funzionare è assicurarsi che tutti gli elementi nella vista di scorrimento, presi insieme, abbiano dei vincoli che alla fine si collegano a tutti i lati della vista di scorrimento e che contribuiscono al sistema AutoLayout in grado di determinare un contenuto scorri la vista che sarà più grande della sua cornice. Sembra che tu stia provando a farlo nel tuo codice, ma forse hai avuto alcuni vincoli superflui che stavano rendendo il contenuto Dimensione troppo piccola.

Inoltre, come altri hanno già detto, con AutoLayout e UIScrollview, non si imposta più esplicitamente contentSize. Il sistema AutoLayout calcola contentSize in base ai tuoi vincoli.

Ho anche trovato questo capitolo di ebook molto utile per farmi capire come funziona tutto questo. Spero che tutto ciò aiuti.


2
GRAZIE per il progetto di esempio! Funziona e, mentre lo guardo, all'inizio non ho trovato alcuna differenza nel mio progetto! Ho copiato le viste nel mio progetto, sospettando qualche altra impostazione oltre ai vincoli, ma ha continuato a funzionare. Questo mi ha portato a notare che il vincolo finale dell'ultimo pulsante del mio progetto ha un aspetto negativo, di fronte ad esso, mentre il tuo ha un valore positivo! La modifica di - in positivo ha abilitato lo scorrimento! Quando apro la barra degli strumenti Pin, ci sono due scelte: Usa il valore corrente della tela, che è negativo, e Scorri la vista (usa il valore corrente) che è positivo ...?!
user1459524

Ah sì. Il valore negativo ridurrebbe effettivamente la dimensione del contenuto della vista di scorrimento, in modo che corrisponda al fatto che il bordo posteriore dovrebbe terminare prima della fine del pulsante. Sono contento che il progetto di esempio abbia aiutato!
Jamie Forrest,

Ha fatto molto. Controlla la mia risposta aggiornata. Sembra che il valore finale sia effettivamente 0 (zero).
user1459524

6
Questa è la cosa triste che dobbiamo condividere screenshot invece di codice. Questo perché Apple incoraggia gli sviluppatori a usare builder invece di fornire API migliori.
Vladimír Slavík,

4
Totalmente poco intuitivo. Gli sviluppatori devono sprecare ore e ore per capire cosa stesse succedendo nella mente dei creatori di XCode.
Josh,

49

LOL benvenuto nel club della stupidità. Sono uno dei fondatori. : D

Per lo scorrimento VERTICALE : l'unico modo per farlo funzionare (iOS 8, Xcode 6 e puro autolayout) è stato aggiungere i seguenti vincoli alla mia vista di scorrimento (tutti relativi alla superview):

  • Pari larghezze
  • Pari Altezze
  • Allineamento al centro Y.
  • Allineamento centro X.

La mia struttura:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...

Questo è il risultato finale:

dimostrazione

Questa è la configurazione:

Impostare A schermo intero

Ed ecco il progetto .

Spero che ciò salverebbe qualcuno dal ANDARE A DORMIRE ALLE 5:00. : D


Grazie mille per l'aiuto! Come hai ottenuto la sottoview di tipo "subview" ?? Sto guardando il tuo progetto in Xcode 6.2, e chiama quei piccoli rettangoli "Subview" con l'unico vincolo che è alto 63px.
Andrew K,

1
Saluti! Quel "Subview" è in realtà un UIVIew. Questo è solo un nome ... Puoi digitare qualsiasi cosa lì. Dai un'occhiata a questa immagine: cl.ly/image/291f1K2N0V3p Nell'argomento del vincolo, le viste secondarie hanno più di un semplice vincolo di altezza. Controlla l'intero elenco dei vincoli per quelle viste qui: cl.ly/image/3l061i123j2i
backslash-f

1
Non riesco ancora a far funzionare lo scrolling: ho notato che le visualizzazioni delle tue subview sono "disattivate" nel tuo progetto. Dopo aver fatto qualche ricerca, sembra che questo sia perché stai usando "classi di dimensioni". In che modo ciò influisce sullo scorrimento? C'è un modo per far funzionare lo scorrimento senza usare questo?
Andrew K,

Inoltre, come hai reso la tua superview molto più lunga della lunghezza predefinita? Sto cercando di aggiungere pulsanti che verranno visualizzati "above the fold" (o fuori schermo) ma ovviamente non posso aggiungerli alla superview se non riesco a trascinarli sulla superview poiché non è abbastanza grande.
Andrew K,

1
dopo una lunga giornata di ricerche e tentativi di fare questo stupido layout, ho trovato questa risposta e ho funzionato al primo tentativo .. Grazie amico .. mi salvi la giornata .. Vorrei poter dare mille voti per questa risposta ..: )
Bobby Stenly

32

Esempio semplice e autonomo

A giudicare dall'elevato numero di voti sulla domanda e dal basso numero di voti sulle risposte, le persone non stanno trovando una soluzione comprensibile e rapida qui. Vorrei provare ad aggiungerne uno. Questo progetto è un esempio autonomo fatto completamente in Interface Builder. Dovresti essere in grado di risolverlo in 10 minuti o meno. Quindi puoi applicare i concetti che hai imparato al tuo progetto.

inserisci qui la descrizione dell'immagine

La domanda originale pone sui pulsanti di scorrimento. Qui uso solo UIViews ma possono rappresentare qualunque vista ti piaccia. Ho anche scelto lo scorrimento orizzontale perché gli screenshot dello storyboard sono più compatti per questo formato. I principi sono gli stessi per lo scorrimento verticale, però.

Concetti chiave

  • L' UIScrollViewdovrebbe utilizzare una sola visualizzazione secondaria. Questo è un 'UIView' che funge da visualizzazione del contenuto per contenere tutto ciò che si desidera scorrere.
  • Rendi la vista del contenuto e il genitore della vista di scorrimento hanno altezze uguali per lo scorrimento orizzontale. (Pari larghezze per lo scorrimento verticale)
  • Assicurarsi che tutto il contenuto scorrevole abbia una larghezza impostata e sia bloccato su tutti i lati.

Inizia un nuovo progetto

Può essere solo un'applicazione a vista singola.

storyboard

In questo esempio creeremo una vista di scorrimento orizzontale. Seleziona il controller di visualizzazione, quindi seleziona Forma libera in Impostazioni dimensioni. Fai la larghezza 1,000e l'altezza 300. Questo ci dà solo spazio sullo storyboard per aggiungere contenuti che scorreranno.

inserisci qui la descrizione dell'immagine

Aggiungi una vista di scorrimento

Aggiungi a UIScrollViewe aggiungi tutti e quattro i lati alla vista principale del controller di visualizzazione.

inserisci qui la descrizione dell'immagine

Aggiungi una vista contenuto

Aggiungi a UIViewcome sottoview alla vista di scorrimento. Questa è la chiave. Non provare ad aggiungere molte visualizzazioni secondarie alla visualizzazione a scorrimento. Basta aggiungere un singolo UIView. Questa sarà la visualizzazione del contenuto per le altre visualizzazioni che si desidera scorrere. Appunta la vista del contenuto alla vista di scorrimento su tutti e quattro i lati.

inserisci qui la descrizione dell'immagine

Pari Altezze

Ora nella struttura del documento, Commandfai clic sia sulla vista contenuto che sulla vista principale della vista di scorrimento per selezionarle entrambe. Quindi impostare le altezze uguali ( Controltrascinare dalla vista contenuto alla vista scorrimento). Anche questa è la chiave. Poiché stiamo scorrendo in senso orizzontale, la vista del contenuto della vista di scorrimento non saprà quanto dovrebbe essere alta a meno che non la impostiamo in questo modo.

inserisci qui la descrizione dell'immagine

Nota:

  • Se stessimo facendo scorrere il contenuto verticalmente, imposteremmo che la larghezza della vista del contenuto fosse uguale alla larghezza del genitore della vista di scorrimento.

Aggiungi contenuto

Aggiungi tre UIViewsecondi e dai loro tutti i vincoli. Ho usato 8 punti di margine per tutto.

inserisci qui la descrizione dell'immagine

vincoli:

  • Vista verde: appuntare i bordi superiore, sinistro e inferiore. Rendi la larghezza 400.
  • Vista rossa: appuntare i bordi superiore, sinistro e inferiore. Rendi la larghezza 300.
  • Vista viola: appuntare tutti e quattro i bordi. Rendi la larghezza qualunque sia lo spazio rimanente (268 in questo caso).

Anche l'impostazione dei vincoli di larghezza è fondamentale in modo che la vista di scorrimento sappia quanto sarà larga la sua vista del contenuto.

Finito

È tutto. Puoi eseguire il tuo progetto ora. Dovrebbe comportarsi come l'immagine a scorrimento nella parte superiore di questa risposta.

Per lo scorrimento verticale, basta scambiare tutte le direzioni di larghezza e altezza in questo esempio (testato e funzionante).

Ulteriore studio


9

ContentSize viene impostato implicitamente applicando i vincoli all'interno di UIScrollView.

Ad esempio, se hai un UIScrollView all'interno di un UIView sarà simile a questo (come sono sicuro che tu sia a conoscenza):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil

Ciò imposterà scrollView per riempire la dimensione di containerView (quindi containerView dovrà avere una certa dimensione).

È quindi possibile regolare il contentSize di UIScrollView impostandolo implicitamente in modo che sia sufficientemente grande da contenere i pulsanti in questo modo:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];

Quindi, ho impostato i vincoli tra scrollView e i pulsanti, e non containerView e i pulsanti? Penso che sia l'unica differenza che sto sfoggiando tra il tuo codice e quello che sto facendo tramite lo storyboard in questo momento.
user1459524

Mi sono reso conto solo dopo la seconda lettura che stai creando una vista CONTAINER e non una vista CONTENT. Sulla base del tuo codice, ho ricreato tutto esattamente nello storyboard e non scorre. Modificherò la mia domanda con alcuni screenshot.
user1459524

1
Quindi il mio tentativo di ricreare il codice nello storyboard non è stato corretto al 100%. Il valore finale dell'ultimo pulsante dovrebbe essere esattamente zero, rispecchiando H: | - [pulsante A] - [pulsante B] - [pulsante C] - | il che non è molto ovvio quando si lavora nello storyboard (o almeno non era per me) ma ora dopo il fatto sembra banale. Adoro il trasferimento automatico, ma quelle piccole cose ti prendono ...
user1459524

Quello che @ user1459524 ha menzionato è stato un problema per me. La mia vista dal basso era un pulsante e il vincolo inferiore era -32 di IB. Ho impostato quello su 0 e si è aggiornato in IB per essere Bottom Space a: superview. Funzionerà, inoltre sembra che tu sia dal lato positivo che funziona. Sembra che potrebbe essere un bug con IB. Spero che aiuti qualcun altro. Ho anche rimosso tutte le viste e ricablato che aiuta quando provo a disporne queste che trovo e di solito non ci vuole molto tempo.
Michael,

8

Ci sono così tante domande sull'uso di AutoLayout con UIScrollView, il punto chiave che ignoriamo è che le viste interne di UIScrollView impongono vincoli alla vista contenuto ma non a UIScrollView stesso. Fare riferimento alla Nota tecnica TN2154 , è possibile trovare:

La classe UIScrollView scorre il suo contenuto modificando l'origine dei suoi limiti. Per farlo funzionare con Layout automatico, i bordi superiore, sinistro, inferiore e destro all'interno di una vista di scorrimento ora significano i bordi della vista contenuto.

La figura seguente mostra che: inserisci qui la descrizione dell'immagine

È possibile trovare lo spazio finale di 500 punti, se il vincolo viene applicato a UIScrollView, la vista verrà persa e dovrebbe essere aggiornato il suo frame. Tuttavia, nessun avviso e nessun errore. Perché tutti i vincoli sono contrari alla visualizzazione del contenuto.

UIScrollView calcolerà la dimensione della vista del contenuto in base ai vincoli delle viste interne. (Ad esempio, la dimensione del contenuto: larghezza = 100 (spazio iniziale) + 200 (larghezza della vista) + 500 (spazio finale), altezza = 131 (spaziatura superiore) + 200 (altezza) + 269 (spaziatura inferiore)

Come aggiungere vincoli per le viste in UIScrollView:

  1. Imaging delle posizioni delle viste nella vista contenuto.
  2. Aggiungi la spaziatura superiore, destra, inferiore, sinistra ai bordi della vista contenuto, inoltre, anche la larghezza e l'altezza di queste viste.

E tutto è fatto.

Un modo semplice per gestire AutoLayout con scrollview è aggiungere una vista contenitore contenente tutte le viste secondarie nella vista di scorrimento.

Conclusione: il punto chiave per comprendere AutoLayout con UIScrollView è che le viste interne creano vincoli rispetto alla vista contenuto ma non a UIScrollView stesso.

codice di esempio allegato


5

La seguente soluzione ha funzionato per me con scrollView con autolayout e senza contentSize :

  1. Trascina e rilascia uno scrollView per viewController e applica tutti i vincoli per coprire lo spazio che desideri.
  2. Trascina e rilascia un UIView all'interno di scrollView e fallo coprire l'intero spazio di scrollView e applica i vincoli per essere in alto, a sinistra, a destra, nello spazio inferiore di scrollView.
  3. Impostare l' altezza (e la larghezza se è necessario lo scorrimento orizzontale) della vista interna in base alla necessità di scorrimento. Questa parte può anche essere eseguita dal codice, se necessario.
  4. Critico . Dopo aver impostato l'altezza su un valore elevato nel punto (3), torna al punto (2) ed assicurati di riportare i valori superiore, sinistro, destro e inferiore a zero poiché Xcode potrebbe averli modificati per te quando forzi modificato l'altezza in (3).

E hai finito. Ora, puoi aggiungere un numero qualsiasi di controlli in questa vista e applicare i vincoli tra loro rilevanti (che non sembrano funzionare senza questa vista). Se non si desidera utilizzare questa vista, è necessario applicare i vincoli per ciascun controllo correlato a scrollView (non correlato tra loro).


Il consiglio travolgente ..............

Critico . Diciamo per chiarezza che UIScrollView è largo 1000 e alto 100. (In effetti normalmente questi valori sarebbero dinamici, ovviamente, a seconda della larghezza del dispositivo ecc. Ma per ora dite solo 1000 di larghezza e 100 di altezza.) Diciamo che state facendo uno scorrimento orizzontale. Quindi inserisci un UIView all'interno di UIScrollView. (Questa è la "vista contenuto".) Imposta tutti e quattro i vincoli della vista contenuto in alto, in basso, in testa, in coda, alla vista di scorrimento. Renderli tutti a zero anche se questo sembra sbagliato. Impostare l'altezza del contenuto UIView su 100 e non pensarci più. Ora: vuoi scorrere in orizzontale, quindi imposta la larghezza della visualizzazione del contenuto su diciamo 1225.

Si noti che la larghezza della vista del contenuto è ora 225 più grande della larghezza della vista di scorrimento principale. Va bene: in effetti, DEVI farlo. Nota che

... NON imposti la larghezza finale su negativo 225 ...

penseresti di dover "abbinare" le larghezze come faresti normalmente . Ma se lo fai, non funzionerà affatto.

Devi impostare i numeri iniziali e finali su ZERO , mai negativo (anche se la larghezza è "più grande")

È interessante notare che puoi effettivamente impostare i numeri iniziali / finali su qualsiasi valore positivo (prova a dire "50") e ti dà una sorta di margine del rimbalzo. (Sembra spesso fantastico: provalo.) Qualsiasi valore negativo su entrambe le estremità "si romperà silenziosamente".

Si noti che, in modo esasperante, spesso Xcode (a partire dalla 7.3.1),

imposterà "utile" quei valori su numeri negativi!

perché cerca di calcolarli automaticamente per te. In tal caso si romperà silenziosamente. Impostare tutti e quattro i valori su zero nella prima istanza. E imposta la larghezza della visualizzazione del contenuto molto più ampia della "1000" nell'esempio.


Modificato: ho finito con l'utilizzo di UITableView invece di UIScrollView per la maggior parte delle mie esigenze. Come tableView mi sembra molto più flessibile e dinamico.


Questa è in realtà la migliore risposta qui. Grazie!
Fattie,

4

Presumo che stai riscontrando problemi con il contentSize. Dai un'occhiata a questo post sul blog su come gestirlo contentSizequando usi un approccio di "AutoLayout" puro. L'essenza di ciò è che i tuoi vincoli definiscono implicitamente la dimensione del contenuto. Non è MAI impostato esplicitamente quando si utilizza AutoLayout. Ho allegato un esempio di progetto alla fine del post sul blog per dimostrare come funziona


3

C'è un pezzo nelle note tecniche che potresti aver guardato. È possibile impostare implicitamente la dimensione del contenuto di una vista di scorrimento utilizzando i vincoli fissati ai bordi della vista di scorrimento.

Ecco un semplice esempio. Crea uno storyboard con una vista, con una vista di scorrimento. Impostare i vincoli delle viste di scorrimento in modo che si adattino alle dimensioni della vista in cui lo si inserisce.

All'interno di quella vista di scorrimento aggiungi una vista singola. Imposta esplicitamente la dimensione di quella vista usando i vincoli (e assicurati che la dimensione sia maggiore della vista di scorrimento).

Ora aggiungi altri quattro vincoli a quella vista interna bloccando i quattro bordi della vista interna alla vista di scorrimento principale. Questi quattro vincoli determineranno l'espansione delle dimensioni del contenuto per adattarsi alla vista interna.

Se si hanno più viste che si desidera aggiungere a una vista di scorrimento, ad esempio disposte orizzontalmente, si bloccherebbe il lato sinistro della prima vista secondaria a sinistra della vista di scorrimento, si bloccherebbero le viste secondarie l'una con l'altra in senso orizzontale e la destra lato dell'ultima vista secondaria sul lato destro della vista di scorrimento. Tali vincoli forzerebbero l'espansione della dimensione del contenuto della vista di scorrimento per adattarsi a tutte le visualizzazioni secondarie e ai relativi vincoli.


3

Se la tua domanda è "Come posso mettere un mucchio di UITextField in un UIScrollView a scorrimento verticale in modo tale che si spostino dalla tastiera quando hanno lo stato attivo", la risposta migliore è:

Non farlo.

Utilizzare invece un UITableViewController con celle statiche.

Ottieni questo comportamento scroll-of-the-way gratuitamente E TUTTI gli inserimenti di contenuto Funzionano solo se il controller della vista viene visualizzato all'interno di un UINavigationController.


3

È necessario organizzare il layout in modo che
ViewControllerViewcontenga ScrollView, ScrollViewcontenga ContainerView, ContainerViewcontenga 2Labels
inserisci qui la descrizione dell'immagine

Quindi segui 3 passaggi per far ScrollViewscorrere il tuo

  1. Impostazione del ScrollViewperno (in alto / a destra / in basso / a sinistra) suViewControllerView
    • Impostazione del ContainerViewperno (in alto / a destra / in basso / a sinistra) suScrollView
    • Imposta Horizontally in Container( non impostare Vertically in Container)
    • Label1pin (in alto / a destra / a sinistra) aContainerView
    • Label1pin (destra / sinistra / in basso ) a ContainerViewe dall'alto aLabel1

inserisci qui la descrizione dell'immagine

QUI è il progetto demo

Spero che questo aiuto


1

L'approccio di autolayout puro funziona magnificamente, ma è piuttosto complicato installarlo se si sta migrando da non autolayout. L'ho fatto alcune volte e ho alcuni consigli generali:

  • Inizia in piccolo: anche se significa ricreare le viste dello storyboard, inizia con pochi elementi e costruisci le viste lentamente, assicurandoti di testare che lo scorrimento funzioni dopo aver aggiunto alcuni elementi.
  • Disattiva traduceAutoresizingMaskIntoConstraints su tutto: questa è sempre stata la causa dei conflitti di vincoli per me.
  • Imposta correttamente i tuoi vincoli UIScrollView: assicurati che la vista di scorrimento sia connessa su tutti i lati alla vista principale, altrimenti non si espanderà affatto.

1

Dopo un po 'di tempo con questo problema, ho finalmente trovato una soluzione. Sto lavorando con storyboard di dimensioni universali (600x600). Ho creato un UIView (contentView) delle dimensioni di scrollView e creato vincoli su Top, Bottom, Leading e Trailing su scrollView. Quindi ho ritagliato manualmente la dimensione del contentView a 600x600. Lo storyboard ha smesso di provare a ridimensionare tutto e ho potuto lavorare, ma la vista sembrava orribile sul dispositivo reale o sul simulatore. Ho realizzato 2 punti di vincolo di queste dimensioni ritagliate.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;

Quindi in viewDidLoad

CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;

Funziona alla grande.


1

Ho trascorso giorni cercando di trovare una soluzione su come utilizzare AutoLayout per visualizzare una Scrollview incorporata, per centrare la scrollview nella schermata visibile, che funziona su tutti i dispositivi / dimensioni dello schermo e con la rotazione dello schermo.

Ho trascorso giorni cercando di farlo solo con Autolayout, e mi sono avvicinato ma mai abbastanza vicino. Quindi alla fine ho dovuto aggiungere anche 3 righe di codice per schermata, in viewDidLoad.

Vedi la soluzione di seguito:

  1. Crea la vista di scorrimento e riempila con qualsiasi oggetto tu voglia
  2. Attiva layout automatico
  3. Quindi centrare ScrollView in verticale e in orizzontale Centra ScrollView
  4. Seleziona la vista e poi 'Aggiungi vincoli mancanti' , questo fa la sua cosa
  5. Il risultato è che vengono generati molti vincoli. Ci sono 2 nuovi creati per la vista: 'Horiz space scrollview to View' e 'Vert space scrollview to view' o viceversa.
  6. Elimina la vista di scorrimento dello spazio Horiz su Visualizza in modo da rimanere con 3 vincoli sulla vista. Il 2 per inserire la vista di scorrimento nella vista e quello per impostare uno spazio verticale tra la vista di scorrimento e la vista
  7. Ora collega il vincolo Vert al tuo codice facendo clic e Ctrl trascinandolo nel file di intestazione e creando un IBOutlet NSLayoutConstraint (ho chiamato il mio vincoloVertVtoSV)
  8. Ora vai al file .m e aggiungi queste righe di codice in viewDidLoad (gioca con la quantità di riempimento per ottenere il centramento verticale corretto)

    if (IPAD)

    {self.constraintVertVtoSV.constant = 150.0; }

  9. questo dovrebbe ora funzionare su tutti i dispositivi ed essere correttamente centrato e scorrere comunque correttamente.


1

Se come me usi semplicemente contenuto statico senza vincoli all'interno della sottoview, come puoi fare in questo modo:

override func viewDidLayoutSubviews() {
    scrollView.contentSize = CGSizeMake(320, 800)
}

1

Problema simile che sto riscontrando oggi con iOS 8.4, Xcode 6.4

C'è una vista che contiene una vista di scorrimento, che contiene una contentView (UIView) che contiene viste secondarie.

Tutto è layout automatico ovunque. I bordi della vista di scorrimento sono fissati ai bordi delle viste principali con vincoli. I bordi della vista del contenuto sono fissati ai bordi della vista di scorrimento con vincoli.

Inizialmente la vista del contenuto si rifiutava di ridimensionare come l'intera larghezza della vista di scorrimento. Ho dovuto aggiungere un ulteriore vincolo alla vista del contenuto per far corrispondere la sua larghezza alla vista di scorrimento principale. Oppure potrei impostare un vincolo contentView.centerX == scrollView.centerX. Uno di questi, oltre a bloccare i bordi, ha improvvisamente ridimensionato la visualizzazione del contenuto.

// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))

Appuntare i bordi della vista del contenuto alla vista di scorrimento usando i vincoli visivi del modulo,

let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]

Uso una routine per scorrere attraverso l'array e aggiungerli a scrollView.


1

Ho affrontato un problema simile. Ho impostato tutti i vincoli e mi chiedevo sempre perché ridimensionasse ancora alcune visualizzazioni secondarie. La mia soluzione era quella di impostare clipsToBounds su YES.


1

In breve tempo puoi usare questa soluzione funzionante.

contraints

ScrollView: Leading, Trailing, Top, Bottom = Superview

ContentView: Leading, Trailing, Top, Bottom = ScrollView. Altezza fissa / relativa al contenuto.

È possibile impostare il vincolo di larghezza (contentView) su una vista di scorrimento uguale, ma selezionare Rimuovi Rimuovi durante il tempo di costruzione perché si aggiungerà quel vincolo a livello di codice. Questo è solo per cui l'IB non si lamenta di avvertimenti.

extension UIView {

    func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
        //Set constraint for scrollview content
        let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
        vwContent.addConstraint(constraint)
        self.layoutSubviews()
    }

}

E nel View Controller viewDidLayoutSubviewschiamo solo questo metodo:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}

0

So che questa è la soluzione di un profano e non è ciò che Apple suggerisce nel documento, ma ha funzionato per me due volte, con contenuti diversi e può essere configurato molto rapidamente: nel controller della vista dello storyboard inserisci UIView. In UIView inserisci una vista tabella, dinamica, 0 celle prototipo, stile normale o raggruppata. Nella vista tabella inserisci una vista di scorrimento, nella vista di scorrimento inserisci contenuto. Questo è tutto, nessuna impostazione nel controller di visualizzazione personalizzato.

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.