iOS SDK Folosind un cursor pentru a curăța un cititor PDF

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ă.

Unde am plecat

Î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:

  • Cuprins
  • UISlider pentru navigare
  • Marcaje
  • Căutare
  • Repere

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ă!

Previzualizare tutorial

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".

Pasul 1: Adăugați fundalul spațial

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.

Pasul 2: Adăugați glisorul de navigare

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.

Pasul 3: Creați un IBOutlet pentru cursor

Î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..

Pasul 4: Redimensionați afișarea cărții

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!

Pasul 5: Inițializați cursorul

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.

Pasul 6: adăugați curățarea paginilor

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.

Pasul 7: Sincronizați cursorul

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ă!

Ar trebui să continui această serie?

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.



Cod