Acest tutorial este o continuare a Razboiul lumilor Proiectul cititor de iPad și va demonstra cum să navigați într-un fișier PDF cu un UISlider când utilizați proiectul Leaves. Pe parcurs, vom face câteva modificări estetice pentru ca interfața să devină mai puțin imersivă.
În tutorialul din săptămâna trecută, v-am prezentat proiectul open source Leaves și am demonstrat cum să configurați un cititor PDF de bază. Cu toate acestea, implementarea Frunze de bază a lăsat mult de dorit din punctul de vedere al utilizatorului. Mai exact, am sugerat următoarele îmbunătățiri:
60% dintre participanții la vot au votat pentru a vedea tutoriale suplimentare fie prin adăugarea unui Tabel de Cuprins, fie prin intermediul unui UISider, așa că vom realiza astăzi. Un alt sondaj a fost inclus în acest post, așadar dacă doriți să vedeți caracteristici suplimentare adăugate la acest proiect sau preferați să trec la un alt subiect SDK pentru iOS, anunțați-mă!
Aceasta este o demonstrație video a ceea ce va crea acest tutorial:
La sfârșitul acestui tutorial, ar trebui să aveți o bună înțelegere a modului în care UISlider
lucrează în mod obiect și o mai bună înțelegere a intervalelor proiectului "Frunze".
Vom începe prin pregătirea interfeței pentru a avea a UISlider
. Am experimentat cu câteva abordări diferite, dar în cele din urmă am decis să mă ocup de un design pe care nu l-am văzut nicăieri altundeva: am micșorat afișarea cărții, am centrat-o în mijlocul ecranului și apoi am adăugat un fundal o galaxie îndepărtată pentru un efect tematic. Apoi am centrat doar pe UISlider
sub carte. Îmi place de fapt modul în care sa dovedit acest lucru, dar recunosc de bună voie că aceasta nu este abordarea cea mai practică. Când construiți o aplicație pentru cititori, este bine ca textul să acopere ecranul complet, așa cum a făcut-o în ultima construcție a proiectului, dar partea plus pentru a adăuga unele elemente de umplutură în jurul cărții este că puteți construi un interfață UI mai imersivă. Asta am încercat să realizez aici.
Pentru a face același lucru, deschideți WOTWViewController.xib fişier. Trageți a UIImage
pe ecranul iPad și dimensiunea imaginii pentru a umple întregul ecran (asigurați-vă că vizualizarea este setată la modul Portret). Apoi, selectați Inspectorul de atribute pentru UIImage
și setați imagine câmp la "space.png" (puteți găsi acest fișier în dosarul "Resurse" din descărcarea acestui post). Acum avem o imagine de fond mult mai rece pentru proiect. Acest lucru ar putea fi ușor de personalizat pentru un alt gen decât Science Fiction.
Apoi trageți a UISlider
obiecte pe vedere. Cu UISlider
selectați, mergeți la "Inspector de mărime". Setați lățimea obiectului la 360, poziția X la 204 și poziția Y la 955. UISiderul ar trebui să fie acum poziționat lângă partea de jos a ecranului și chiar dedesubtul locului în care va fi afișată cartea.
În acest moment trebuie să sincronizăm UISlider
în Interface Builder cu o proprietate în controlerul nostru vizualizare WOTW. Cu fișierul XIB încă deschis, faceți clic pe fila Editor asistent din bara de instrumente Xcode. Procedând astfel, se va deschide o fereastră de editor care ar trebui să conțină WOTWViewController.h fișierul (dacă conține alt fișier, selectați unul corect din pictograma "Fișiere înrudite" din partea stângă sus a panoului de editor). Acum, CTRL + faceți clic pe UISlider
în fișierul XIB și trageți linia care apare pe panoul ferestrei editorului. Eliberați când se afișează postul "Introduceți colecția de ieșire, acțiune sau colecție". Va apărea un dialog care vă va solicita un nume pentru conexiunea IBOutlet. Denumiți priza pageSlider
și faceți clic pe conectați. Interface Builder va adăuga acum codul necesar pentru această priză pentru a fi utilizat în proiectul dvs..
După cum sa menționat în primul tutorial din această serie, LeavesViewController
clasa conține a UIView
denumit leavesView
unde apare desenul paginii. Cadrul lui leavesView
este setat să oglindească LeavesViewController
în loadView
, după cum se arată mai jos:
LeavesViewController.m
- (void) încărcareView [super loadView]; leavesView.frame = self.view.bounds; leavesView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [auto.view addSubview: leaveView];
În cazul nostru, dorim leavesView
cadru pentru a umple doar un subset al controlerului de vizualizare, nu întregul ecran.
Avem câteva opțiuni aici. Cea mai ușoară soluție pare să fie schimbarea pur și simplu a dimensiunii leavesView
cadru manual pe linia 3 de mai sus în LeavesViewController.m fişier. Cu toate acestea, veți aminti asta LeavesViewController
face parte din codul oficial al proiectului Frunze și toate modificările noastre au fost făcute până acum WOTWViewController
, care este o subclasă de LeavesViewController
. Aceasta este, în general, o abordare mult mai ușor de întreținut decât alternativa: hacking-ul în codul de bază al proiectului pentru nevoile specifice situației dvs. și apoi lupta continuă cu actualizările proiectului prin fuzionarea repetitivă sau rescrierea modificărilor comunității. Într-un astfel de scenariu, veți găsi neglijarea voinței celor mai recente clădiri stabile ale proiectului. Nu vrei să te găsești blocată în această situație.
Deci, care este o alternativă mai bună? Pentru că am moștenit-o leavesView
obiect în WOTWViewController
, putem doar să facem schimbările noastre în -(Void) viewDidLoad
metodă.
În WOTWViewController.m, adăugați următoarele rânduri de cod:
- (vid) viewDidLoad [super viewDidLoad]; [auto-> leftView setFrame: CGRectMake (0.0f, 0.0f, 563.0f, 845.0f)]; [auto-> leftView setCenter: self.view.center];
Pe linia 3 de mai sus sunăm LeavesViewController
implementarea a loadView
, și apoi personalizăm leavesView
cadru pe cont propriu. Linia 4 stabilește cadrul la o lățime și o înălțime pe care le-am găsit potrivită, iar linia 5 centrează cadrul în mijlocul controlerului de vizualizare WOTW.
NOTĂ: Te întrebi de ce folosesc sintaxa funky pentru a accesa leavesView
obiect? Acolo pare a fi un bug în GCC 4.2.1 care necesită acest lucru. Comentariile cu o perspectivă mai mult apreciate.
Dacă construiți și executați proiectul acum, ar trebui să vedeți cititorul WOTW în centrul ecranului cu un cursor de dedesubt pentru navigare. Bineînțeles, glisorul nu funcționează încă, așa că hai să ne întoarcem!
Când se lansează aplicația noastră, dorim să setăm valorile glisoarelor minime, maxime și curente în funcție de PDF-ul încărcat pentru aplicație. De asemenea, trebuie să specificăm ce se va întâmpla când se schimbă valoarea cursorului. Vom face asta în WOTWViewController.m fișier cu următoarele rânduri de cod:
- (vid) viewDidLoad [super viewDidLoad]; [auto-> leftView setFrame: CGRectMake (0.0f, 0.0f, 563.0f, 845.0f)]; [auto-> leftView setCenter: CGPointMake (auto.view.center.x, self.view.center.y - 20.0f)]; [self.pageSlider addTarget: acțiune auto: @selector (turnPageWithSlider :) forControlEvents: UIControlEventValueChanged]; auto.pageSlider.minimumValue = 0.0; auto.pageSlider.maximumValue = (float) ([numărul personalOfPagesInLeavesView: auto-> leavesView] - 1); auto.pageSlider.value = auto-> leavesView.currentPageIndex;
Linia 8 de mai sus stabilește un selector care ar trebui să fie apelat atunci când valoarea cursorului se modifică. În mod implicit, se va apela selectorul continuu pe măsură ce butonul glisant se mișcă. Cu toate acestea, puteți dezactiva acest lucru setând glisorul continuu
valoarea "NO", care va face ca selectorul să fie apelat numai după eliberarea butonului glisant.
Linia 9 de mai sus stabilește valoarea minimă la 0. Aceasta este potrivită deoarece PDF-ul din frunze este referit cu un index bazat pe 0.
Linia 10 de mai sus cheamă numberOfPagesInLeavesView:
pentru a seta valoarea maximă a cursorului și ajustează pentru un indice bazat pe 0 scăzând 1 din rezultat.
În cele din urmă, linia 11 stabilește valoarea curentă a cursorului la leavesView
proprietate currentPageIndex
.
Vom scrie acum logica care ar trebui să apară atunci când turnPageWithSlider:
se selectează selectorul.
Adăugați următorul cod în fișierul de implementare WOTW:
- (void) turnPageWithSlider: (id) expeditor int pageIndex = (int) [valoare auto.pageSlider]; [auto.pageSlider setValue: (float) pageIndex]; auto-> leftView.currentPageIndex = pageIndex;
Valoarea returnată de la UISlider
este al pluti
tip de date. În linia 3 de mai sus, introduceți această valoare la un număr întreg și păstrați-o în pageIndex
variabil.
Pe linia 4, facem invers: am tipcast pageIndex
la un flotor și apoi actualizați valoarea cursorului. Care-i rostul? Nu este acest lucru redundant? Nu, pentru că atunci când introducem valoarea cursorului la un număr întreg, restul restului. Acest lucru este important pentru că nu vrem să ne întoarcem, de exemplu, la pagina 1.23 sau 20.56, vrem să ne întoarcem la pagina 1 sau 20. Acest pas forțează utilizatorul să traverseze PDF-ul în ceea ce este probabil modul așteptat.
Linia 5 de mai sus stabilește leavesView
proprietate pagina curenta
, care va forța automat și actualizarea afișării cărții.
Dacă construiți și rulați proiectul acum, ar trebui să puteți trata prin carte. Cu toate acestea, lipsește un detaliu important: dacă întoarceți paginile prin glisarea manuală, valoarea cursorului rămâne aceeași. Pentru aceasta trebuie să intrăm în delegatul LeavesView.
Fereastra personalizată oferă mai multe metode delegate care sunt chemați la punctele-cheie ale animației. Unul dintre ele este leavesView: didTurnToPageAtIndex:
. Adăugați următoarea logică pentru a actualiza cursorul atunci când se numește această metodă delegată:
- (void) leavesView: (LeavesView *) leavesView didTurnToPageAtIndex: (NSUInteger) pageIndex if ((int) self.pageSlider.value! = pageIndex) auto.pageSlider.value = (float) pageIndex;
Cu ajutorul codului de mai sus, implementarea slider-ului nostru ar trebui să fie completă!
După cum am menționat la începutul acestui tutorial, există încă multe caracteristici care ar putea fi adăugate la acest proiect. Dacă doriți să continuați această serie, votați pentru funcția pe care doriți să o vedeți mai jos. În caz contrar, puteți vota pentru mine să trec la un subiect complet diferit de SDK pentru iOS (nu ezitați să sugerați unul în secțiunea comentarii). Sondajul se va închide sâmbătă dimineața, 10 septembrie.