• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

UIScrollview – Guida completa all’uso

By IgnazioC | on 7 Novembre 2011 | 15 Comments
Senza categoria

Le UISCrollview fanno parte dell’UIKit framework e sono utilizzate dalla stessa Apple per la realizzazione di componenti avanzati quali le UIWebView e UITableView.

Come è chiaro dal nome, le UISCrollView sono una subclass diretta di UIView quindi in termini di OOP possiamo dire che è una UIView specializzata.

Ma quale sarà mai la specializzazione di una UIScrollView? Ovviamente quella di scrollare, di rendere cioè possibile la visualizzazione di un contenuto più grande della UIScrollView stessa.

L’incipit della refernce (link ) dice:

The UIScrollView class provides support for displaying content that is larger than the size of the application’s window. It enables users to scroll within that content by making swiping gestures, and to zoom in and back from portions of the content by making pinching gestures.

(La classe UISCrollview permette di visualizzare contenuti che sono più grandi della dimensione della finestra dell’applicazione. Permette all’utente di scrollare il contenuto tramite swipe e zoomare tramite pinch).

Non so perché Apple faccia quel riferimento all’application window, direi che si tratta di un’imprecisione, perché affinché si possa scrollare è necessario che il contenuto sia più grande della UIScrollview stessa indipendentemente dalla dimensione della uiwindow.

Come funzionano le UIScrollView?

Esamineremo il funzionamento della scrollview creando una piccola applicazione di esempio, apriamo quindi xcode e creiamo un nuovo progetto di tipo “single view application”. Io l’ho chiamato devappScrollview ed ho tolto il flag sia da “Use storyboard” e sia da “Use Automatic reference counting” (che ci posso fare, sono vecchia scuola 🙂 )

In questo articolo non staremo molto a guardare lo stile di programmazione, quindi andremo a creare l’interfaccia direttamente nel metodo viewDidLoad del primo UIViewController.
Identifichiamo quindi questo metodo e posizioniamoci subito dopo [super viewDidLoad];

Come tutte le UIView anche la UISCrollview ha la sua proprietà frame che identifica il rettangolo dove verrà visualizzata.

Allochiamo e inizializiamo una nuova UIScrollView con il codice:

UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 30, 300, 400)];

Aggiungiamola quindi alla view principale del viewcontroller e non dimentichiamo di rilasciarla:

[self.view addSubview:scroll];
[scroll release];

Compiliamo e osserviamo il risultato…



Sembra che non sia successo nulla, perché come tutte le uiview anche la scrollview di default si presenta con il colore trasparente.

Per renderci conto di dove è effettivamente posizionata la scrollview coloriamola di rosso inserendo questo codice subito dopo l’inizializzazione:

[scroll setBackgroundColor:[UIColor redColor]];

Adesso il simulatore mostra la posizione della scrollview:



La UIScrollview abbiamo detto che fa da contenitore, quindi proviamo ad aggiungere un’immagine al suo interno e vediamo cosa succede.

Ho scelto appositamente un’immagine con una dimensione un pò particolare 400 x 1222, l’idea è quella di permettere quindi di scrollare l’immagine in orizzontale per poterla visualizzare. Questa è l’immagine utilizzata (cliccateci sopra per vedere le dimensioni effettive e per scaricarla e usarla nel vostro progetto):



Aggiungiamo quindi questa immagine al progetto xcode (file->add file to “project”) e creiamo una nuova UIImageview da inserire dentro la UIScrollview. Per chiarezza riporto tutto il metodo viewdidload:

- (void)viewDidLoad
{
    [super viewDidLoad];
	UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 30, 300, 400)];
	[scroll setBackgroundColor:[UIColor redColor]];
	
	UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1222, 400)];
	[imageview setImage:[UIImage imageNamed:@"panorama_orizzonte_medio_big.jpg"]];
	[scroll addSubview:imageview];
	[imageview release];
	
	[self.view addSubview:scroll];
	[scroll release];
}

Il risultato è questo:



Però c’è un grosso problema…non scrolla!

Abilitiamo lo scroll

Affinché la UIScrollView sappia quanto e come scrollare è necessario impostare la proprietà contentSize di questo oggetto, facciamolo e ricompiliamo:

- (void)viewDidLoad
{
    [super viewDidLoad];
	UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 30, 300, 400)];
	[scroll setBackgroundColor:[UIColor redColor]];
	
	UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1222, 400)];
	[imageview setImage:[UIImage imageNamed:@"panorama_orizzonte_medio_big.jpg"]];
	[scroll addSubview:imageview];
	[imageview release];
	
	[self.view addSubview:scroll];
	[scroll release];
}

Anche se lo screenshot è piccolino si riesce a vedere la barra di scorrimento orizzonale, segno che siamo riusciti nel nostro compito.



La gestione dello zoom

La gestione dello zoom è leggermente diversa dalla logica che abbiamo visto adesso e usa il concetto di delegate. Quando l’utente fa pinch sulla UISCrollview questa invoca sul suo delegate il metodo:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView al quale il delegate risponde con una UIView.

Ci si potrebbe chiedere come mai la scrollview semplicemente non faccia in autonomia uno zoom sulla UIView visualizzata ed il motivo è che utilizzando il delegate si ha, ad esempio, la possibilità di fornire una view diversa per diversi livelli di zoom. Supponiamo di avere due versioni della foto del panorama, una a bassa risoluzione ed un’altra ad altissima risoluzione, per ovvie ragioni di memoria all’inizio carichiamo quella a bassa risoluzione, poi se l’utente inizia a fare zoom oltre un certo livello potremmo sostituire l’immagine a bassa risoluzione con una porzione dell’immagine ad alta. Un pò come succede quando si usa una mapview o strumenti analoghi.

Per abilitare lo zoom dobbiamo quindi modificare il viewcontroller per renderlo conforme al protocollo UIScrollViewDelegate, aggiungiamo inoltre una variabile di istanza di tipo UIImageview. Il file .h del nostro viewcontroller si presenterà quindi in questo modo:

#import 

@interface ViewController : UIViewController <UIScrollViewDelegate> {
	UIImageView *imageview;
}

@end

Nel metodo viewdidload impostiamo quindi il delegate della scrollview e utilizziamo la variabile di istanza piuttosto che la variabile locale:

- (void)viewDidLoad
{
    [super viewDidLoad];
	UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 30, 300, 400)];
	[scroll setDelegate:self];
	[scroll setBackgroundColor:[UIColor redColor]];
	
	imageview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1222, 400)];
	[imageview setImage:[UIImage imageNamed:@"panorama_orizzonte_medio_big.jpg"]];
	[scroll addSubview:imageview];
	
	[scroll setContentSize:CGSizeMake(1222, 400)];
	[self.view addSubview:scroll];
	[scroll release];
}

notate che ho tolto anche il release della imageview perché voglio che sia valida anche all’uscita di questo metodo, però non dobbiamo generare memory leak, quindi aggiungiamo il medo dealloc in cui rilasciamo tutto.

-(void)dealloc {
	[imageview release];
	[super dealloc];
}

..ok ok lo so..se avessi abilitato ARC mi sarei risparmiato un pò di rogne 😉

Aggiungiamo il metodo per la gestione dello zoom limitandoci a ritornare l’oggetto imageview:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
	return imageview;
}

Se proviamo a compilare a questo punto, ci accorgiamo che lo zoom non funziona ancora… e questo ci porta ad esaminare due altre propery dell’oggetto UISCrollView: maximumZoomScale e minimumZoomScale. Se guardiamo la documentazione notiamo che per entrambe il valore di default è 1.0 il che significa che il contenuto non può essere né zoomato né rimpicciolito. Impostiamo rispettivamente questi valori a 2.0 e 0.5 e ricompiliamo il progetto: finalmente siamo riusciti ad attivare anche questa funzionalità.



Paging con UIScrollview

Un utilizzo molto comune delle UISCrollview è quello di creare browser di fotografie, visualizzabili tramite swipe.

Se avessimo memoria infinita il compito sarebbe piuttosto semplice, basterebbe creare tante UIImageView quante sono le immagini da visualizzare, posizionarle all’interno della scrollview ed avremmo già realizzato il nostro browser. Purtroppo ci tocca essere un tantino più attenti e cercare di risparmiare quanta più memoria possibile. Decidiamo quindi di mantenere in memoria soltanto 3 immagini, quella corrente, quella precedente e quella successiva, questo ci permetterà di occupare una quantità fissa di memoria, indipendente dal numero di foto che compongono la galleria.

Un’idea di quello che andremo a realizzare lo si vede in questa simulazione:



Modifichiamo il nostro progetto inserendo 3 variabili di istanza di tipo UIImageview e una variabile intera che memorizzerà il numero della pagina corrente:

@interface ViewController : UIViewController  {
	UIImageView *imageview1;
	UIImageView *imageview2;
	UIImageView *imageview3;
        int currentPage;
}
@end

e non dimentichimoci del metodo dealloc:

-(void)dealloc {
	[imageview1 release];
	[imageview2 release];
	[imageview3 release];
	[super dealloc];
}

Dichiariamo quindi una costante globale in cui memorizziamo il numero di foto che compongono la galleria:

const int numImages = 5;

e passiamo infine a generare la scrollview sempre all’interno del metodo viewdidload.

In questo caso il contentview della scrollview sarà uguale alla larghezza di ogni singola immagine per il numero delle immagini che compongono la galleria.

UIScrollView* scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 30, 400, 300)];
[scroll setDelegate:self];
[scroll setContentSize:CGSizeMake(300 * numImages, 400)];

Passiamo quindi alla generazione delle tre UIImageview, ciascuna 300px più a destra della precedente e ne impostiamo la proprietà tag così da poterle recuperare con un po’ di matematica:

imageview1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)];
[imageview1 setImage:[UIImage imageNamed:@"tiger0.jpg"]];
[imageview1 setTag:1];
imageview2 = [[UIImageView alloc] initWithFrame:CGRectMake(300, 0, 300, 400)];
[imageview2 setTag:2];

imageview3 = [[UIImageView alloc] initWithFrame:CGRectMake(600, 0, 300, 400)];
[imageview3 setTag:3];
[scroll addSubview:imageview1];
[scroll addSubview:imageview2];
[scroll addSubview:imageview3];

L’idea è quella di spostare queste imageview durante l’operazione di scrolling così da simulare la presenza di un numero illimitato di imageview.

Per fare questo aggiungiamo nel nostro viewcontroller anche il metodo
-(void)scrollViewDidScroll:(UIScrollView*)scrollView che viene richiamato durante la fase di scrolling.

All’interno del metodo calcoliamo l’attuale posizione della scrollview:

const CGFloat currPos = scrollView.contentOffset.x;

da questo valore calcoliamo la pagina che è attualmente visualizzata:

const NSInteger selectedPage = lroundf(currPos / 300.0); 

calcoliamo infine quale delle tre imageview è al centro dello schermo:

const NSInteger zone = 1 + (selectedPage % 3); 
const NSInteger nextPage = selectedPage + 1;
const NSInteger prevPage = selectedPage - 1;

Passiamo quindi a configurare l’imageView successiva, verificando di non essere arrivati alla fine della nostra galleria. Recuperiamo l’imageview attraverso la sua proprietà tag e la spostiamo nella posizione successiva alla schermata attuale impostandone la proprietà image:

	if (nextPage < numImages)
	{
		NSInteger nextViewTag = zone + 1;
		if (nextViewTag == 4)
			nextViewTag = 1;
		UIImageView* nextView = (UIImageView*)[scrollView viewWithTag:nextViewTag];
		nextView.frame = CGRectMake(nextPage * 300, 0, 300, 400);
		NSString *str = [NSString stringWithFormat:@"tiger%d.jpg", nextPage];
		UIImage* img = [UIImage imageNamed:str];
		nextView.image = img;
	}

Lo stesso lavoro va fatto con la imageview precedente:

if (prevPage >= 0)
	{
		NSInteger prevViewTag = zone - 1;
		if (!prevViewTag)
			prevViewTag = 3;
		UIImageView* prevView = (UIImageView*)[scrollView viewWithTag:prevViewTag];
		prevView.frame = (CGRect){.origin.x = prevPage * 300, .origin.y = 0.0f, .size = prevView.frame.size};
		NSString *str = [NSString stringWithFormat:@"tiger%d.jpg", prevPage];
		UIImage* img = [UIImage imageNamed:str];
		prevView.image = img;
	}

Eccoci al termine della nostra guida, compilate ed eseguite il programma e, se avete seguito tutto correttamente, dovreste godervi la vostra nuova galleria fotografica.

Se avete problemi con il progetto presentato, questo è il link per scaricare l’esempio completo.

Share this story:
  • tweet

Tags: Frameworkphotogallery xcodeUIKit frameworkUIScrollViewUIScrollView pagingUIScrollView scroll and zoomUIScrollViewDelegateviewForZoomingInScrollView

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • T#055 – Sfruttiamo le ScrollView per visualizzare al meglio più oggetti

    22 Giugno 2010 - 8 Comments

Author Description

15 Responses to “UIScrollview – Guida completa all’uso”

  1. 7 Novembre 2011

    Ignazioc

    Per qualsiasi problema discutiamone pure sul forum! 🙂

  2. 8 Novembre 2011

    Frugghi

    Sbaglio o non hai impostato contentSize nel codice? In ogni caso ottimo articolo molto interessante come sempre!

  3. 8 Novembre 2011

    ignazioc

    veramente c’è 🙂
    [scroll setContentSize:CGSizeMake(300 * numImages, 400)];
    grazie per i complimenti

  4. 8 Novembre 2011

    Frugghi

    Forse il mio iPad è impazzito ma io nell’articolo non la vedo! (non ho scaricato il progetto)

  5. 8 Novembre 2011

    ignazioc

    giuro che c’è 🙂 nel box di codice immediatamente successivo al testo:
    “In questo caso il contentview della scrollview sarà uguale alla larghezza di ogni singola immagine per il numero delle immagini che compongono la galleria.”

  6. 8 Novembre 2011

    Frugghi

    Pardon, io mi riferivo al pezzo di codice dopo: “Affinché la UIScrollView sappia quanto e come scrollare è necessario impostare la proprietà contentSize di questo oggetto, facciamolo e ricompiliamo”

  7. 8 Novembre 2011

    ignazioc

    🙂 gulp! è saltata…grazie per la correzione!

  8. 8 Novembre 2011

    Francesco

    domandina sulle scrollview a cui non riesco a trovar risposta…

    nella mia app avrei la necessita di visualizzare piu uitextfield (ma anche uilabel e uibutton) di quante non ce ne stiano in una vista standard quindi pensavo di usare la scrollview.

    è possibile da IB “disegnare” la scrollview con dimensioni maggiori a quelle standard e poi vederla tramite scroll sul device/simulatore? come? oppure devo per forza “disegnarla” tramite codice per usare la scrollview?

    Grazie in anticipo per la risposta

  9. 9 Novembre 2011

    ignazioc

    da IB non ho trovato l’opzione per impostare il contentsize però puoi disegnare le tue textfield selezionarle e poi dal menù cliccare su “embed in scrollview” con un pò di pazienza potresti riuscire..però considera che non vedi scrollare da interface builder..ma lo vedi solo a runtime.

  10. 10 Novembre 2011

    Sergio


    Francesco:

    domandina sulle scrollview a cui non riesco a trovar risposta…
    nella mia app avrei la necessita di visualizzare piu uitextfield (ma anche uilabel e uibutton) di quante non ce ne stiano in una vista standard quindi pensavo di usare la scrollview.
    è possibile da IB “disegnare” la scrollview con dimensioni maggiori a quelle standard e poi vederla tramite scroll sul device/simulatore? come? oppure devo per forza “disegnarla” tramite codice per usare la scrollview?
    Grazie in anticipo per la risposta

    Guarda questo video dovrebbe fare al caso tuo XCode 4 Tutorial Creating A Scroll View

    ciao

  11. 13 Novembre 2011

    yassassin

    ciao, se ho capito bene, in questo modo le immagini sono contenute all’interno dell’applicazione e questo ha due effetti collaterali:
    – per aggiungere altre immagini devo rilasciare una nuova versione dell’app
    – la dimensione dell’app dipende dal numero delle immagini incluse al suo interno, e questo mi limita nella quantità

    come potrei fare ad avere una galleria simile che però pesca le immagini dal web?
    grazie!!!

  12. 16 Novembre 2011

    Ivan

    per rispondere a yassassin, il metodo che mi viene in mente è creare un bel xml con titolo e indirizzo web dell’immagine che vuoi visualizzare e poi con un parser puoi visualizzare o anche scaricare l’immagine. Così ogni volta che vuoi aggiungere un’immagine basta che vai a modificare l’xml e non l’app

  13. 26 Agosto 2012

    Aldo

    anche sul forum ho aperto una discussione , sto cercando di zoomare tutta la view con dei bottoni al interno…..avete qualche idea come si fa ?

  14. 20 Ottobre 2012

    Marc0x

    complimenti…spiegazione chiara ed esaustiva!!! 😉

  15. 30 Ottobre 2012

    Marco

    Ciao,
    premetto che sono alle prime armi 🙂

    Ho seguito la prima parte del tutoria (fino al paging) ed ho un problema con lo zoom.
    In pratica, simulando il pinch, mi fa lo zoom di tutta la scrollview ma non dell’immagine, che rimane delle stesse dimensioni.
    Provo a spiegarmi meglio…
    L’area in cui è presente l’immagine si “zooma” ma l’immagine resta uguale. La vedo muoversi, rimanendo presumibilmente agganciata all’angolo in alto a sinistra della scrollview. Dopodichè posso fare pan su un’area più grande (perché zoomata appunto) e vedere l’immagine, non zoomata, scrollando verso Su-Sinistra.

    Cosa mi sto perdendo?
    Grazie

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO