Et av de første problemene som oppstår når du bygger en mobil webapp fra grunnen, er mengden plass som forbrukes av nettleserens adressefelt. Denne opplæringen vil vise hvordan du kan gjenvinne skjermfast eiendom ellers tapt til adressefeltet, mens du regner med orienteringsendringer, innholdshøydproblemer og interne dokumentkoblinger.
Visse aspekter av applikasjoner eller teknikker som brukes i denne opplæringen, har endret seg siden den ble opprinnelig publisert. Dette kan gjøre det litt vanskelig å følge med. Vi anbefaler å se på disse nyere opplæringsprogrammene på samme emne:
Et av de vanskeligste aspektene ved å designe for mobile enheter er den begrensede mengden av skjermplass tilgjengelig. Mobilnettapplikasjoner må være strømlinjeformet og intuitivt for å kunne konkurrere med innfødte applikasjoner, og tilstedeværelsen av nettleserens brukergrensesnitt trekker ofte bare fra brukeropplevelsen og nettstedets estetiske som helhet.
For eksempel, vurder følgende skjermbilde for mobilnettsted:
Ovennevnte skjermbilde ble tatt på en iPhone 4 med både Mobile Safari adresselinjen og verktøylinjen vist.
Ta en titt på det samme skjermbildet uten nettleserens brukergrensesnitt:
IPhone-versjonen av nettstedet fikk 60 piksler ved å fjerne adressefeltet øverst og 44 piksler ved å fjerne knappestangen nederst for en total gevinst på 104 logiske piksler med vertikal skjermplass (mengden plass oppnådd på Android-enheter varierer , men resultatet er likt). Når du prøver å bygge en innslukkende opplevelse, er det lett å fortelle fra skjermbildene over hvilken stor forskjell en slik liten forandring kan gjøre.
Dessverre har de store mobilnettleserne ennå ikke gitt utviklere en enkel og universell metode for å bytte nettleserens brukergrensesnitt på eller av. Det er imidlertid to vanlige tilnærminger for å få jobben gjort, og begge vil bli behandlet i denne opplæringen.
Hvis webappen din bare målretter mot iOS, så er den ideelle løsningen å sette følgende metatag i del av HTML-dokumentet ditt:
Hvis du gjør det, fjerner du både nettleserens adresselinje og verktøylinjen fra Mobile Safari, som vist på det andre skjermbildet ovenfor.
I tillegg til det faktum at denne koden vil arbeider kun pålitelig med iOS-enheter, Det er et annet stort problem med denne tilnærmingen: Det vil bare fungere etter at brukeren har lagt til nettstedet til startskjermen og når brukeren starter nettstedet uavhengig av Mobile Safari.
Jeg har lest ubekreftede rapporter om at metakoden-tilnærmingen faktisk vil fungere noen Android-enheter også, men det fungerer sikkert ikke på min Nexus S og synes ikke å være offisielt støttet av Android i det hele tatt.
Dette er åpenbart mindre enn ideelt. Å legge til nettsteder på IOS-startskjermbildet er noe av en obskure iOS-funksjon som mange brukere ikke engang vet, er mulige, og det er usannsynlig å bruke mens de tilfeldigvis surfer på nettet.
Kanskje en nettleserleverandør en gang vil forene og levere en enkelt plattforms metatag for finkornet kontroll over nettleserens brukergrensesnitt uten å hindre den normale nettleserprogrammets strømning (hva livet ville være som om dette faktisk skjedde). Inntil da må vi ta ting i våre hender, den gode gammeldags måten: ved å bruke JavaScript.
counter~~POS=TRUNC: Tillater utviklere å kontrollere tilstedeværelsen av adresselinjen og / eller fanebladet gir kreativ frihet til utviklere på bekostning av sluttbrukerens frihet og den generelle nettleseropplevelsen. Uten et konsistent UX-mønster for å navigere tilbake eller legge inn en ny nettadresse, blir brukerne forvirret mens du surfer og i noen tilfeller ikke i stand til å forlate nettstedet uten å fullstendig tilbakestille nettleseren.
Counter-kontra: Opprette et nytt UX-mønster som gir utviklere mulighet til å bestemme tilstedeværelsen eller fraværet av nettleserkontroller samtidig som sluttbruker kontroll over navigasjonen holdes (kanskje ved en kombinasjon av en uttoningseffekt og "dobbelt-trykk" -bevegelsen eller kanskje av tvinger fullskjerm apps til å lansere i et nytt vindu) kunne finne en balanse mellom begge interessene.
Mange av de nettverksrammer som er tilgjengelig på tvers av plattformer, er nå tilgjengelige for å stole på hva som egentlig er en JavaScript-hack for å komme så nært som mulig for å få en fullskjerm-opplevelse. Følgende rammer inkluderer alle noen variasjon av JavaScript-løsningen jeg skal demonstrere i denne opplæringen:
For de av dere som bare vil ha koden uten fortellingen:
Jeg er vert for den ovennevnte koden på GitHub: Gist, så vær fri til å gaffel, modifisere eller foreslå endringer. Bare vær oppmerksom på at dette i beste fall er en nettleseravhengig hack. Det kan endres i fremtiden. Det kan ikke dekke alle kasser. Det er untested på Blackberry og Windows Phone 7.
OPPDATERING 9/3/2011:
Takket være tilbakemeldingen fra John Boxall nedenfor, har jeg lagt til en ekstra betinget i "load" event lytteren. De hideAddressBar ()
funksjonen vil nå bare bli kalt dersom brukeren ikke har begynt å rulle før "last" -hendelsen blir utløst.
For de av dere som ønsker å lære nøyaktig hvordan og hvorfor dette snille lille tricket fungerer, les videre!
I utgangspunktet utgjør tricket det som kan kondenseres til en enkelt linje med JavaScript:
window.scrollTo (0, 1);
De scrollTo
samtale er en metode for vindu
nettleserobjekt med følgende signatur:
scrollTo (x, y);
Det første argumentet kontrollerer avstanden for å rulle vinduet på x-aksen, og det andre argumentet styrer avstanden for å rulle vinduet på y-aksen.
Det generelle konseptet er at mens vi ikke teknisk kan fjerne nettleserens kontroller fra nettleseren, kan vi bla ned visningsportinnholdet ned for å fjerne adresselinjen fra vinduet.
Så hvorfor bare flytte Y-aksen 1 piksel? Skal det ikke være 60 piksler for iPhone? Det var også min første tankegang. Adressefeltet er imidlertid ikke teknisk del av dokumentvisningsporten. I stedet for å faktisk rulle innholdet ned 60 piksler, utnytter vi faktisk en WebKit-særegenhet (feil?) Som automatisk fjerner adresselinjen når scrollTo
Metoden kalles. I testingen var jeg i stand til å oppnå ønsket effekt på iOS ved å sette Y-verdien til et heltall, inkludert -10, 0, 1 eller 60. Imidlertid oppnådde bare positive heltall på den ønskede effekten i Android, og dermed gjorde "1 "den beste Y-offseten som skal brukes til nettleserhakken.
Det neste trinnet er å bestemme når du skal ringe scrollTo
metode. Ideelt sett bør dette skje like etter at siden laster. Alle følgende implementeringer fungerte i testingen min og er listet i rekkefølge av eleganse:
Legge til en hendelseslytter:
window.addEventListener ("load", funksjon () window.scrollTo (0, 1););
Legge til en inline hendelse lytter:
Innenfor en innebygd manus
tag (for de som føler seg opprørsk):
Hvis du prøver alle tre av disse prøvene på Android, bør ting fungere svømmende (selv om det tredje eksempelet er spesielt styggt). Men hvis du prøver det ovenfor på iOS, vil ingenting skje.
Av grunner som ikke er helt klare for meg, er Mobile Safari på iOS ikke i stand til å bruke rullehakk med en av de ovennevnte hendelseslytterne alene.
For at dette skal fungere på iOS, må du lage en liten forsinkelse mellom når hendelseslytteren brenner og når
scrollTo
metode utfører.
Dette kan enkelt gjøres med setTimeout
metode som vist:
window.addEventListener ("load", funksjon () setTimeout (funksjon () window.scrollTo (0, 1);, 100);
Metodens signatur for setTimeout
funksjonen er:
setTimeout (kode, millisekunder, [lang])
Så i mitt eksempel ga jeg en anonym funksjon som inneholder scrollTo
Ring for å bli henrettet etter en forsinkelse på 100 millisekunder. Oddly nok har ovennevnte fortsatt jobbet for meg, uavhengig av heltalet som er oppgitt for millisekundforsinkelsen. Det virket med -100, 0 og 1 like godt som 100. Følgelig er min anbefaling å bruke 0 for millisekunder argumentet.
På dette tidspunktet må adresselinjen som gjemmer JavaScript-kodestykket, se ut som et av følgende eksempler:
Eventlytter:
Fullskjerm Test
Inline hendelse lytter:
Flott! Så nå kan vi fortsette å faktisk bygge noe nyttig, ikke sant? Dessverre ikke. Det er fortsatt flere leserespesifikke problemer som kan ødelegge denne hacken.
Hva om innholdet ditt ikke er stort nok til å fylle hele skjermen? I så fall vil du ikke ha en vertikal rulleknapp, og trikset som vises ovenfor, virker ikke. I tillegg til å bare legge til mer innhold på siden din, er det minst tre andre mindre restriktive metoder du kan ta for å håndtere dette problemet.
Initial-Scale
Den første tilnærmingen er å modifisere initial-skala
av nettsiden din til innholdet ditt fyller hele visningsporten. Du kan gjøre dette med følgende metatag:
Du må leke rundt med initialverdien til du finner skalaen / zoom som samsvarer med dine spesifikke behov.
Den andre tilnærmingen er å bruke et enkelt CSS-attributt. Du kan søke en tilstrekkelig stor min-høyde
verdi til enten kropp
tag eller et annet blokknivåelement på siden din for å ta hensyn til den tomme hvite plassen. Men du må være forsiktig her av to grunner: Den eksakte pixelverdien som trengs av min-høyde
Attributt vil variere avhengig av initial-skala
(dvs. zoom) på siden og verdien vil endres hvis brukeren roterer fra stående til liggende modus eller omvendt. Den grunnleggende syntaksen for å angi minhøydeattributtet på kroppsmerket er vist nedenfor:
kropp min-høyde: 900px;
Igjen: Den faktiske pixelverdien som brukes, er avhengig av startskalaen / zoomen på nettstedet ditt. Du må kanskje gå ganske høyt eller ganske lavt.
Den tredje tilnærmingen er å dynamisk sjekke document.height
eiendom mot window.outerHeight
eiendom og deretter øke størrelsen på document.height
når nødvendig.
Å følge JavaScript kodestykket er en ikke-ramme løsning på dette problemet:
På linjer 5 ovenfor har jeg lagt til en tilsynelatende vilkårlig mengde polstring (+50). Dette var nødvendig for at effekten kunne virke på både iOS og Android. Jeg har også måtte flytte anropet til setTimeout
da iOS ikke ville produsere automatisk rulle umiddelbart etter innstillingen document.body.style.height
. Det jeg syntes å være spesielt merkelig var at jeg ikke bare måtte omplassere setTimeout
ring, men for iOS måtte jeg også legge til en tilsynelatende vilkårlig forsinkelse på +50 hvis jeg nettopp hadde endret dokumenthøyde. Dette var ikke tilfelle i utgangspunktet (når du bruker laste
lytter uten å sette inn en ny verdi for dokumenthøyde).
Variasjoner på nettleserenes hack er allerede vidt implementert på nettet. Det er imidlertid minst en brukstilfelle der det å tvinge nettleseren til å bla til 0,1, er nøyaktig feil tilnærming: Besøkende kommer til nettstedet ditt via et anker (a.k. intern) -link. For å imøtekomme denne kanten skal du bare ringe scrollTo (0, 1)
hvis hash-taggen ikke er til stede i nettadressen. For å implementere denne tilnærmingen er alt vi må gjøre, sjekke for tilstedeværelsen av en verdi i window.location.hash
og deretter pakke inn vår laste
hendelse lytter innenfor det betingede. Å gjøre det etterlater oss med noe som følger:
hvis (! window.location.hash) window.addEventListener ("load", funksjon () 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 ); );
Et annet problem du kan støte på omhandler endringer i enhetsorientering. På IOS, når en bruker roterer telefonen fra stående modus til liggende modus, vil ikke rulleforskyvningen endres automatisk (Android ser ikke ut til å lide av dette problemet). Dette betyr at brukeren din vil bli igjen et sted lenger ned på siden enn det er beregnet.
Løsningen for dette er å sette en hendelseslytter på window.onorientationchange
å bli varslet når orienteringen endres, og deretter å utføre window.scrollTo (0, 1)
ring igjen etter at endringen skjer.
Dette virker som en god tid til å begynne å refactere koden ved å dele koden som er ansvarlig for å gjemme adresselinjen til en selvstendig funksjon. Etter å ha gjort det, er vi igjen med følgende:
funksjon hideAddressBar () hvis (! 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 );
Ovennevnte løsning ser ut til å fungere bra for meg både på Android og iOS, men det er enda et problem som kan være relevant for prosjektet ditt: Hva om brukeren har rullet betydelig ned på siden før du endrer enhetens orientering? I så fall vil tilbakestilling av displayet til 0, 1 føre til at brukeren mister plass i dokumentet. Regnskapsføring av dette er svært implementeringsspesifikke, men det er bare å sette en y-akse-terskel og deretter bare tilbakestille rulleforskyvningen til 0, 1 dersom brukeren ikke allerede har rullet over denne grensen.
Enkelte rammer, for eksempel SenchaTouch, vil faktisk låse adresselinjen utenfor skjermen ved å hindre at brukeren ruller utover en gitt y-akse-terskel. Dette er sikkert mulig, men jeg vil ikke diskutere hvordan du gjør det her, da jeg finner denne løsningen å være et betydelig bruksproblem, spesielt på Android. Men hvis du er fast bestemt på å oppnå denne effekten, må du sannsynligvis eksperimentere med window.pageYOffset
Egenskap.
Etter min kunnskap er det for øyeblikket ikke en løsning for å fjerne verktøylinjen / knappelinjen på iOS fra bunnen av Mobile Safari med JavaScript alene. Den eneste måten jeg er klar over for å oppnå denne effekten er meta tag-tilnærmingen som er forklart i begynnelsen av denne opplæringen. Korriger meg hvis jeg tar feil!
En overveielse med fremgangsmåten ovenfor som ikke er diskutert, er hvordan man skal håndtere brukere som besøker fra en ikke-mobil eller ikke-støttet nettleser. Det finnes en rekke forskjellige metoder for å bestemme hvilken nettleser som nå får tilgang til nettstedet ditt. Hvis du jobber med et skriptspråk på server-siden, vil du kanskje finne ut om brukeren er på en mobilenhet på det tidspunktet siden genereres og bare gi dette hacket når det er nødvendig. Kanskje en mer robust tilnærming ville være å gjøre testingen dynamisk med JavaScript. Bruk av denne vurderingen er utenfor omfanget av denne opplæringen, men vær så snill å la dine forslag komme i kommentarene.
Browser hacks som den jeg har beskrevet for å skjule adressefeltet, utfordrer beste praksis. Gjennomførelsen jeg har forklart i denne opplæringen har blitt testet på en Android Nexus S, iPhone 3GS og en iPhone 4, men det er ganske mulig at jeg har savnet et kanten tilfelle et sted. Jeg er heller ikke helt sikker på at implementeringen som vises vil fortsette å fungere som i fremtiden, derfor var jeg ganske overrasket over å finne så mange av de primære nettrammene (f.eks. IUI, jQuery Mobile, SenchaTouch) og fremtredende nettsteder (for eksempel Gmail, Yahoo, Apple) stole på noen tilpasset variasjon av denne hacken. Årsaken, jeg tror, er enkel: en bedre, ikke-javascript løsning eksisterer for øyeblikket ikke.
Jeg hadde tre hovedintensjoner med å skrive en slik grundig veiledning om hva som kan virke som et trivielt problem.
Først ønsket jeg å gi en ren JavaScript-kode for å oppnå denne effekten som er mer robust enn de fleste andre jeg har møtt. Jeg håper at jeg har oppnådd det ved å ta imot orienteringsendringer, ankerforbindelser og innholdshøydproblemer.
For det andre ønsket jeg å fjerne noe av magien bak hvilke rammer som SenchaTouch eller IUI har gjort denne effekten mulig. Da jeg først bestemte meg for å bruke SenchaTouch til et frilanseprosjekt for en tid siden, var "magien" av rammen for å lage apps fylt skjermen en av de primære UX-effektene som appellerte til meg. Det er viktig å innse at denne samme effekten enkelt kan implementeres i ren JS uavhengig av om du velger å bruke et JavaScript-rammeverk i prosjektet ditt.
Endelig er den viktigste grunnen til at jeg ønsket å ta opp dette problemet i så stor detalj, å øke bevisstheten for hvor lett denne tilnærmingen egentlig er. Til tross for at variasjoner av dette trikset har blitt mye vedtatt, tror jeg at det i beste fall er en inelegant kludge og i verste fall en upålitelig nettleseravhengig hack som kanskje eller ikke kan fortsette å fungere i fremtiden. Jeg ønsker å oppfordre de i nettleservirksomheten og web / mobilutviklingssamfunnet som helhet til å presse for en mer standardbasert, JavaScript-selvstendig tilnærming for å håndtere denne UX-vurderingen. Jeg tror meta-tag-metoden Apple har implementert, er et godt skritt i riktig retning, men som nevnt ovenfor er det ikke tilstrekkelig å møte behovene til utviklingssamfunnet.
Det virkelige spørsmålet er: hva synes du? La oss snakke om det i kommentarfeltet nedenfor.
Jeg har ingen tvil om at noen av våre lesere kan være i stand til å forbedre koden jeg har gitt i denne opplæringen. Hvis du ser noe i dette innlegget som kan optimaliseres eller forbedres, vennligst gi tilbakemelding nedenfor! Du kan også nå meg via Twitter (@markhammonds), selv om det noen ganger tar meg en stund å svare på Tweets eller DMs. Den beste måten å nå meg på er enten i kommentarene under eller med kontaktskjemaet på Mobileuts +. Hvis jeg godtar et av forbedringsforslagene dine, oppdaterer jeg dette innlegget og citerer navnet ditt eller håndteringen!
Ønsker ikke å ta mitt ord for noen av de ovennevnte?
Se på følgende ressurser som jeg snublet over mens jeg forsket på dette innlegget: