Una dintre primele probleme întâmpinate atunci când construim o aplicație web mobilă de la zero este cantitatea de spațiu consumată de bara de adrese a browserului. Acest tutorial va demonstra modul de recuperare a imobilelor de pe ecran, pierdute altfel în bara de adrese, în timp ce contabilitatea modificărilor de orientare, a problemelor privind înălțimea conținutului și a legăturilor interne ale documentelor.
Anumite aspecte ale aplicațiilor sau tehnicilor utilizate în acest tutorial s-au schimbat de când au fost publicate inițial. Acest lucru ar putea face un pic dificil de urmat de-a lungul. Vă recomandăm să consultați aceste tutoriale mai recente pe același subiect:
Unul dintre aspectele cele mai dificile de proiectare pentru dispozitivele mobile este disponibilitatea spațiului disponibil pe ecran. Aplicațiile web mobile trebuie să fie raționalizate și intuitive pentru a concura cu aplicațiile native, iar prezența interfeței de utilizator a browserului deseori scade doar experiența utilizatorului și estetica site-ului în ansamblul său.
De exemplu, luați în considerare următoarea fotografie de pe site-ul web mobil:
Imaginea de mai sus a fost făcută pe un iPhone 4, atât cu bara de adrese Mobile Safari, cât și cu bara de instrumente afișată.
Acum, aruncați o privire la aceeași captură de ecran fără interfața browserului:
Versiunea iPhone a site-ului a câștigat 60 de pixeli prin eliminarea barei de adrese din partea de sus și a celor 44 de pixeli prin eliminarea barei de butoane din partea inferioară pentru un câștig total de 104 pixeli logici ai spațiului pe ecran vertical (spațiul obținut pe dispozitivele Android variază , dar rezultatul este similar). Când încerci să construiești o experiență imersivă, este ușor să afli de pe capturile de ecran deasupra a ceea ce o mare diferență o poate face o mică schimbare.
Din păcate, marile browsere web mobile nu au oferit dezvoltatorilor încă o metodă ușoară și universală pentru a activa sau dezactiva interfața browser-ului. Cu toate acestea, există două abordări comune pentru a obține o treabă și ambele vor fi abordate în acest tutorial.
Dacă aplicația dvs. web vizează numai iOS, atunci soluția ideală este să setați următoarea meta tag în parte a documentului dvs. HTML:
Procedând astfel, veți elimina complet atât bara de adrese a browserului, cât și bara de instrumente de la Mobile Safari, așa cum se arată în cea de-a doua imagine de ecran de mai sus.
În plus față de faptul că acest cod va funcționează fiabil numai pe dispozitive iOS, există o altă problemă majoră cu această abordare: acesta va funcționa numai după ce utilizatorul a adăugat site-ul web la ecranul de pornire și atunci când utilizatorul lansează site-ul independent de Mobile Safari.
Am citit rapoarte neconfirmate că abordarea meta tag va funcționa efectiv niste Dispozitive Android, de asemenea, dar cu siguranță nu funcționează pe Nexus S și nu pare să fie susținut oficial de Android.
Acest lucru este evident mai puțin decât ideal. Adăugarea de site-uri web pe ecranul de pornire iOS este oarecum o caracteristică obscură pe care mulți utilizatori chiar nu știu că este posibilă și este puțin probabil să o utilizeze în timp ce navighează ocazional pe web.
Poate că furnizorii de browsere de o zi se vor uni și vor furniza o singură etichetă meta-platformă pentru controlul fin în browser-ul UI, fără a obstrucționa fluxul normal de aplicații din browserul web (care ar fi viața dacă s-ar întâmpla acest lucru). Până atunci, va trebui să luăm lucrurile în mâinile noastre într-un mod bun de modă veche: folosind JavaScript.
Contrapunct: Permițând dezvoltatorilor să controleze prezența bara de adrese și / sau bara de taburi oferă libertate creativă dezvoltatorilor în detrimentul libertății utilizatorilor finali și experienței globale de navigare. Fără un model consistent UX pentru navigarea înapoi sau introducerea unei noi adrese URL, utilizatorii vor deveni confuzi în timpul navigării și, în unele cazuri, incapabili de a părăsi site-ul fără a reseta complet browserul.
Counter-contrapunct: Crearea unui nou model UX care să permită dezvoltatorilor să determine prezența sau absența controalelor browserului, menținând simultan controlul utilizatorului asupra navigației (poate printr-o combinație a efectului de decolorare și a gestului "dublu-apăsare") sau poate prin forțând aplicațiile pe ecran complet să se lanseze într-o fereastră nouă) ar putea ajunge la un echilibru între ambele interese.
Multe dintre cadrele de aplicații web încrucișate, disponibile acum, au ajuns să se bazeze pe ceea ce este în esență un hack-uri JavaScript care să vină cât mai aproape posibil de a oferi o experiență de ecran complet. Următoarele cadre includ toate variantele soluției JavaScript pe care o voi demonstra în acest tutorial:
Pentru cei care doriți doar codul fără narațiune:
Am găzduit codul de mai sus pe GitHub: Gist, deci nu ezitați să vă schimbați, să modificați sau să sugerați modificări. Rețineți că acest lucru este, cel mult, un hack dependent de browser. Se poate schimba în viitor. Este posibil să nu acopere fiecare caz de margine. Acesta nu este testat pe Blackberry și Windows Phone 7.
UPDATE 9/3/2011:
Datorită feedback-ului primit de la John Boxall de mai jos, am adăugat încă o condiție în ascultătorul evenimentului "load". hideAddressBar ()
funcția va fi apelată numai dacă utilizatorul nu a început să deruleze înainte de declanșarea evenimentului "încărcare".
Pentru cei care doriți să aflați exact cum și de ce funcționează acest truc mic, citiți mai departe!
În esență, trucul se ridică la ceea ce poate fi condensat într-o singură linie de JavaScript:
window.scrollTo (0, 1);
scrollTo
apel este o metodă a fereastră
obiect de browser cu următoarea semnătură:
scrollTo (x, y);
Primul argument controlează distanța de derulare a ferestrei pe axa x, iar al doilea argument controlează distanța pentru a derula fereastra pe axa y.
Conceptul general este că, în timp ce nu putem elimina din punct de vedere tehnic comenzile browserului din browserul web, putem derula conținutul ferestrei de vizualizare în jos pentru a elimina bara de adrese din fereastră.
Deci, de ce să mișcăm numai pixelul axei Y? Nu ar trebui să fie 60 de pixeli pentru iPhone? Acesta a fost și gândul meu inițial. Cu toate acestea, bara de adrese nu face parte din punct de vedere tehnic din fereastra de vizualizare a documentului. Mai degrabă decât de fapt derularea conținutului cu 60 de pixeli, de fapt, profităm de o particularitate WebKit (bug?) Care va elimina automat bara de adrese atunci când scrollTo
se numește metoda. În testul meu am reușit să obțin efectul dorit pe iOS prin setarea valorii Y la orice număr întreg, inclusiv -10, 0, 1 sau 60. Cu toate acestea, pe Android, numai numerele pozitive au atins efectul dorit, făcând astfel "1 "cel mai bun offset Y de folosit pentru hack-ul browserului.
Următorul pas este să determinați când să sunați scrollTo
metodă. În mod ideal, acest lucru ar trebui să se întâmple imediat după încărcarea paginii. Toate aplicațiile de mai jos au lucrat în testările mele și sunt listate în ordine de eleganță:
Adăugarea unui ascultător al evenimentului:
window.addEventListener ("load", funcția () window.scrollTo (0, 1););
Adăugarea unui ascultător de eveniment inline:
Într-un embedded scenariu
tag (pentru cei care se simt rebeli):
Dacă încercați toate cele trei dintre aceste mostre pe Android, lucrurile ar trebui să funcționeze din plin (chiar dacă cel de-al treilea exemplu este foarte urât). Cu toate acestea, dacă încercați cele de mai sus pe iOS, nimic nu se va întâmpla.
Din motive care nu sunt foarte clare pentru mine, Mobile Safari pe iOS este incapabil să aplice hack-ul cu oricare dintre ascultătorii de evenimente de mai sus.
Pentru ca acest lucru să funcționeze pe iOS, trebuie să realizați o mică întârziere între momentul în care ascultătorul evenimentului se declanșează și când
scrollTo
metoda execută.
Acest lucru se poate face cu ușurință cu setTimeout
metoda demonstrată:
window.addEventListener ("load", funcția () setTimeout (funcție () window.scrollTo (0, 1);, 100);
Semnătura metodei pentru setTimeout
funcția este:
setTimeout (cod, milisecunde, [lang])
Deci, în exemplul meu am oferit o funcție anonimă care conținea scrollTo
apel să fie executat după o întârziere de 100 milisecunde. În mod ciudat, cele de mai sus au lucrat pentru mine, indiferent de numărul întreg prevăzut pentru întârzierea de milisecundă. A lucrat cu -100, 0 și 1 la fel de bine ca 100. În consecință, recomandarea mea este să folosiți 0 pentru argumentul milisecunde.
În acest moment, bara de adrese care ascunde fragmentul JavaScript ar trebui să pară ca unul dintre următoarele exemple:
Ascultător de evenimente:
Testarea pe întreg ecranul
In-line ascultător de eveniment:
Grozav! Deci, acum putem continua să construim ceva util, nu? Din nefericire nu. Există încă mai multe probleme specifice browserului, care pot afecta această hack.
Ce se întâmplă dacă conținutul dvs. nu este suficient de mare pentru a umple întregul ecran? În acest caz, nu veți avea o bară de derulare verticală, iar trucul demonstrat mai sus nu va funcționa. Pe lângă faptul că adăugați mai mult conținut pe pagina dvs., există cel puțin alte trei metode mai puțin restrictive pe care le puteți lua pentru a rezolva această problemă.
Initial-Scale
Prima abordare este modificarea Scara inițială
a paginii dvs. web până când conținutul dvs. umple întregul port de vizualizare. Puteți face acest lucru cu următoarea meta-etichetă:
Va trebui să jucați cu valoarea inițială până când veți găsi suma scării / zoom-ului care se potrivește cu nevoile dvs. specifice.
A doua abordare este utilizarea unui atribut CSS simplu. Puteți aplica un număr suficient de mare min înălțime
valoare fie pentru corp
eticheta sau orice alt element de nivel de blocare de pe pagina dvs. pentru a explica spațiul alb gol. Cu toate acestea, trebuie să fiți atenți aici din două motive: valoarea exactă a pixelilor necesară min înălțime
atributul va varia în funcție de Scara inițială
(adică zoom) a paginii, iar valoarea se va modifica dacă utilizatorul se rotește de la portret la modul peisaj sau invers. Sintaxa de bază pentru setarea atributului min-height pe eticheta corporală este prezentată mai jos:
corp min-height: 900px;
Din nou: valoarea reală a pixelilor utilizate depinde de scala inițială / zoom-ul site-ului dvs. Este posibil să trebuiască să mergeți destul de înalt sau destul de jos.
Cea de-a treia abordare este de a verifica dinamic document.height
proprietate împotriva window.outerHeight
de proprietate și apoi dinamic crește dimensiunea document.height
când este necesar.
Urmărirea fragmentului de cod JavaScript reprezintă o soluție non-cadru pentru această problemă:
Pe liniile 5 de mai sus, am adăugat o sumă aparent arbitrară de umplutură (+50). Acest lucru era necesar pentru ca efectul să funcționeze atât pe iOS, cât și pe Android. De asemenea, a trebuit să repoziționez apelul setTimeout
deoarece iOS nu ar produce auto-defilare imediat după setare document.body.style.height
. Ceea ce mi sa părut deosebit de ciudat a fost că nu numai că trebuie să repoziționez setTimeout
apel, dar pentru iOS a trebuit să adaug o întârziere aparent arbitrară de +50 dacă tocmai am schimbat înălțimea documentului. Acest lucru nu a fost cazul inițial (atunci când se utilizează sarcină
ascultător fără a seta o nouă valoare pentru înălțimea documentului).
Variațiile privind hack-ul browserului de mai sus sunt deja implementate pe scară largă pe web. Cu toate acestea, există cel puțin un caz de utilizare în cazul în care forțarea browserului să defileze la 0,1 este exact o abordare greșită: vizitatorii care vin pe site-ul dvs. printr-o legătură ancoră (a.k.a. internă). Pentru a acomoda acest caz de margine, trebuie doar să apelați scrollTo (0, 1)
dacă eticheta hash nu este prezentă în adresa URL. Pentru a implementa această abordare, tot ce trebuie să facem este să verificăm prezența unei valori în window.location.hash
și apoi împachetați-ne sarcină
ascultător de evenimente în acea condiție. Făcând acest lucru ne lasă ceva de genul:
dacă ! window.location.hash) window.addEventListener ("load", funcția () if (document.height <= window.outerHeight + 10) document.body.style.height = (window.outerHeight + 50) +'px'; setTimeout( function() window.scrollTo(0, 1); , 50 ); else setTimeout( function() window.scrollTo(0, 1); , 0 ); );
O altă problemă cu care vă confruntați se referă la schimbările de orientare ale dispozitivului. În iOS, atunci când un utilizator rotește telefonul din modul portret în modul peisaj, offsetul de derulare nu va fi modificat automat (Android nu pare să sufere de această problemă). Acest lucru înseamnă că utilizatorul dvs. va fi lăsat undeva în jos de pagină decât este destinat.
Remedierea pentru aceasta este de a seta un ascultător de evenimente window.onorientationchange
pentru a fi notificat atunci când orientarea se schimbă și apoi pentru a executa window.scrollTo (0, 1)
apelați din nou după ce apare schimbarea.
Acest lucru pare a fi un moment bun pentru a începe refactorizarea codului prin împărțirea codului responsabil pentru ascunderea efectivă a barei de adrese într-o funcție independentă. După aceasta, am rămas cu următoarele:
funcția hideAddressBar () if (! window.location.hash) if (document.height <= window.outerHeight + 10) document.body.style.height = (window.outerHeight + 50) +'px'; setTimeout( function() window.scrollTo(0, 1); , 50 ); else setTimeout( function() window.scrollTo(0, 1); , 0 ); window.addEventListener("load", hideAddressBar ); window.addEventListener("orientationchange", hideAddressBar );
Soluția de mai sus pare să funcționeze excelent atât pentru Android, cât și pentru iOS, dar există încă o problemă care poate sau nu poate fi relevantă pentru proiectul dvs. Ce se întâmplă dacă utilizatorul a derulat în mod semnificativ pagina înainte de a schimba orientarea dispozitivului? În acest caz, resetarea afișajului la 0, 1 ar determina pierderea locului de utilizator în document. Contabilitatea pentru acest lucru este foarte specifică pentru implementare, dar principala este stabilirea unui prag pentru axa y și apoi resetarea decalajului de defilare doar la 0, 1 dacă utilizatorul nu a derulat deja acest prag.
Unele cadre, cum ar fi SenchaTouch, vor bloca barul de adrese de pe ecran, împiedicând utilizatorul să deruleze dincolo de un anumit prag al axei y. Acest lucru este cu siguranță posibil, dar nu voi discuta cum să procedez aici, deoarece consider că această soluție reprezintă o problemă semnificativă de utilizare, în special pe Android. Cu toate acestea, dacă sunteți determinat (ă) să atingeți acest efect, va trebui probabil să experimentați cu window.pageYOffset
atribut.
Din cunoștințele mele, în prezent nu există o soluție pentru eliminarea barei de instrumente / barei de butoane din iOS din partea de jos a browserului Mobile Safari, cu doar JavaScript. Singura modalitate prin care știu să realizez acest efect este abordarea meta tag explicată la începutul acestui tutorial. Corectează-mă daca greșesc!
O analiză cu abordarea de mai sus, care nu a fost încă discutată, este modul în care se pot ocupa utilizatorii care vizitează un browser web care nu este mobil sau nu este suportat. Există o serie de metode diferite pentru a determina ce browser accesează în prezent site-ul dvs. Dacă lucrați cu un limbaj de scripting pe partea de server, este posibil să doriți să determinați dacă utilizatorul se află pe un dispozitiv mobil în momentul generării paginii și să furnizeze acest hack atunci când este necesar. Poate că o abordare mai robustă ar fi să faceți dinamic testarea cu JavaScript. Aplicarea acestei considerații este dincolo de sfera de aplicare a acestui tutorial, dar vă rugăm să lăsați sugestiile dvs. în comentarii.
Amplificatoarele de browser, precum cea pe care am descris-o pentru a ascunde bara de adrese, sfidează cele mai bune practici. Implementarea pe care am explicat-o în acest tutorial a fost testată pe un Android Nexus S, un iPhone 3GS și un iPhone 4, dar este destul de posibil că am pierdut un caz de margine undeva. De asemenea, nu sunt sigur că implementarea afișată va continua să funcționeze așa cum este în viitor, motiv pentru care am fost destul de surprins să găsesc atât de multe cadre web primare (de exemplu, iUI, jQuery Mobile, SenchaTouch) și proeminente site-uri web (de exemplu, Gmail, Yahoo, Apple) bazându-se pe unele variante personalizate ale acestei hack-uri. Motivul este, cred, simplu: o soluție mai bună, non-javascript nu există în prezent.
Am avut trei intenții principale în scris un astfel de tutorial în profunzime cu privire la ceea ce poate părea o problemă trivială.
În primul rând, am vrut să furnizez un fragment de JavaScript curat pentru atingerea acestui efect, care este mai robust decât majoritatea celorlalți pe care i-am întâlnit. Sper că am realizat acest lucru adaptând schimbările de orientare, legăturile de ancorare și problemele legate de înălțimea conținutului.
În al doilea rând, am vrut să risipesc o parte din magia din spatele cadrelor cum ar fi SenchaTouch sau iUI au făcut posibil acest efect. Când am decis inițial să folosesc SenchaTouch pentru un proiect independent de ceva timp în urmă, "magia" cadrului pentru a face aplicații să umple ecranul a fost unul dintre efectele primare UX care mi-au făcut apel. Este important să realizăm că același efect poate fi implementat cu ușurință în JS pur, indiferent dacă alegeți sau nu să utilizați un cadru JavaScript în proiectul dvs..
În cele din urmă, principalul motiv pentru care am dorit să abordez această problemă într-un mod atât de detaliat este de a crește gradul de conștientizare cu privire la cât de nestatornic este această abordare cu adevărat. În ciuda faptului că variațiile acestui truc au devenit pe scară largă, cred că este cel mai bine un cludge inelegant și, în cel mai rău caz, un hack care nu poate fi încredințat de browser care poate sau nu poate continua să funcționeze în viitor. Aș dori să îi îndemn pe cei din businessul de browsere și pe comunitatea de dezvoltare web / mobilă ca întreg să facă apel la o abordare independentă bazată pe standarde, independentă de JavaScript, care să se ocupe de această analiză UX. Cred că metoda meta-tag-ului pe care Apple a implementat-o este un pas important în direcția cea bună, dar, așa cum am menționat mai sus, nu este suficient să se răspundă nevoilor comunității de dezvoltare.
Întrebarea adevărată este: ce crezi? Să vorbim despre asta în secțiunea de comentarii de mai jos.
Nu mă îndoiesc că unii dintre cititorii noștri ar putea să îmbunătățească codul pe care l-am furnizat în acest tutorial. Dacă vedeți ceva în această postare care ar putea fi optimizat sau îmbunătățit, vă rugăm să lăsați feedbackul de mai jos! De asemenea, puteți să mă contactați prin Twitter (@markhammonds), deși uneori îmi durează ceva timp pentru a răspunde la mesajele Tweets sau DM. Cea mai bună modalitate de a mă atinge este fie în comentariile de mai jos, fie în formularul de contact pe Mobileuts +. Dacă accept una dintre sugestiile dvs. pentru îmbunătățire, voi actualiza această postare și va cita numele sau mâna!
Nu vreau să-mi iau cuvântul pentru niciuna dintre cele de mai sus?
Aruncați o privire asupra următoarelor resurse pe care le-am întâlnit în timp ce cercetați acest post: