Ta strona używa ciasteczek (cookies), dzięki którym nasz serwis może działać lepiej. Rozumiem

Restaurant Finder - NativeScript tutorial - część 2

Po długiej przerwie spowodowanej zakończeniem dużego projektu powracam z pozostałymi częściami samouczka od zera do bohatera. W poprzedniej części pokazałem jak stworzyć główny ekran aplikacji, teraz uzupełnimy go o dodatkową funkcjonalność - geolokalizację. Ta część również nie będzie wymagała lokalnie zainstalowanego środowiska, skorzystamy z NativeScript Playground.

 

Co będziemy dzisiaj robić?

  1. Dodamy brakujący przycisk, widoczny tylko, jeśli użytkownik pozwoli aplikacji na dostęp do pozycji GPS

  2. Pobierzemy lokalizację z GPS po kliknięciu w przycisk i przekażemy ją do innego widoku aplikacji

  3. Dodamy kolejny prosty ekran, w którym wyświetlimy pobraną lokalizację.

 

Geolokalizacja w projekcie

Otwieramy projektu z poprzedniego artykułu dostępny tutaj. Projekt można pobrać na dysk twardy lub utworzyć swojego “forka” (odpowiednik forka z systemu kontroli wersji). Jeśli wolisz githuba, projekt dostępny jest tu.

W Playgroundzie w menu “Explorer” po lewo znajdź i otwórz plik home.component.html. Poniżej tego menu znajduje się panel “Components”. Elementy, które są tam dostępne, można przeciągać metodą drag&drop prosto do plików html. Znajdź na samym dole komponent “Location” i przeciągnij go za zamykający tag typu Button. Zwróć uwagę, że Playground sam sformatował kod, a w lewym panelu “Explorer”, przy plikach home.component.html i home.component.ts pojawiła się gwiazdka. Playground sam dodał strukturę html oraz fragment logiki, która mu odpowiada. Aby zobaczyć dodany element dodajmy wiersz z automatyczną wysokością do głównego kontenera GridLayout przed wierszem z maksymalną wysokością i dodajmy do nowo dodanego StackLayout odpowiedni indeks wiersza.



 

Jeśli sprawdzisz teraz aplikację na swoim urządzeniu, zobaczysz nowy przycisk “Show location”. Po wciśnięciu pojawi się zapytanie, czy wyrażasz zgodę na korzystanie z GPS i jeśli odpowiesz twierdząco, zobaczysz swoje położenie we współrzędnych geograficznych!

Dla pewności, aktualny kod możesz sprawdzić tutaj.

Jeśli nie korzystasz z Playgrounda lub chcesz dowiedzieć się w jaki sposób uzyskaliśmy dostęp do lokalizacji GPS, kontynuuj czytanie, jeśli nie, możesz przejść do rozdziału aktualizacja widoku.

Niektóre funkcjonalności NativeScripta są opcjonalne i dołącza się je do projektu jako pluginy. Tak też jest w przypadku dostępu do GPSa. Będziemy potrzebować plugin nativescript-geolocation. Korzystając z NativeScriptowego CLI instalujemy nasz plugin z wiersza poleceń.

tns plugin add nativescript-geolocation

Jeśli plugin został poprawnie dodany, w pliku home.component.ts importujemy dodaną funkcjonalność.

import * as geoLocation from "nativescript-geolocation";

Musimy teraz sprawdzić czy urządzenie uzyskało już dostęp do lokalizacji. Funkcja do sprawdzenia pozwolenia zwraca obiekt typu Promise przyjmujący wartość typu boolean.



 

Jeśli aplikacja jest włączana po raz pierwszy lub dostęp nie został udzielony musimy poprosić użytkownika o pozwolenie. Po raz kolejny zostanie zwrócony asynchroniczny obiekt typu Promise.

geoLocation.enableLocationRequest().then(() => {});

Cała funkcja powinna wyglądać następująco:



 

Po więcej informacji dotyczących obiektów typu Promise odsyłam np. tu.

Jeśli udało się uzyskać pozwolenie, otworzymy subskrypcję lokalizacji - będziemy nasłuchiwać jej zmian (funkcja showLocation w powyższym fragmencie kodu). Służy do tego funkcja pluginu - watchLocation(successCallback: successCallbackType, errorCallback: errorCallbackType, options: Options): number;

Jako pierwszy argument podajemy funkcję zwrotną, która zostanie wykonana przy emitowaniu nowej lokalizacji. Druga jest funkcja zwrotna do wywołania przy wystąpieniu błędu. Ostatnim argumentem jest obiekt typu Options, dzięki któremu możemy zdefiniować np. żądaną dokładność pomiarów, co jaką odległość lub w jakich odstępach czasowych emitować nową lokalizację.



 

Zamiast logowania obiektu location do konsoli (console.dir(location)), przypiszmy lokalizację do lokalnej zmiennej, do której będziemy mieć dostęp w komponencie.


 


Aktualizacja widoku

Nasz użytkownik nie musi znać swoich współrzędnych. Wystarczy, że aplikacja pozwoli mu na wyszukiwanie lokali po lokalizacji, którą pobierze sama w tle. Zmodyfikujemy teraz naszą strukturę i pozbędziemy się niepotrzebnych elementów. Jedyna nowa rzecz jaką potrzebujemy to przycisk, który pojawi się tylko, jeśli użytkownik zezwoli na dostęp do lokalizacji i uda się ją określić.

Zamiast ostatniego StackLayoutu, w naszym kontenerze w home.component.html, wstawmy element typu Button. Warunek dla jego wyświetlania mamy już w linijce 13 - *ngIf="currentGeoLocation".



 

Po zaktualizowaniu struktury nie zobaczymy od razu naszego przycisku. We wcześniejszym etapie, to użytkownik musiał dotknąć “Show location” aby poprosić o dostęp do geolokalizacji. Wywołajmy zatem funkcję enableLocationServices() w Angularowej funkcji ngOnInit w home.component.ts, aby aplikacja zrobiła to samodzielnie, zaraz po załadowaniu głównego ekranu.



app.css


rest_finder_p2_cropped

 

Jeśli bacznie przyjrzysz się teraz interfejsowi naszego głównego ekranu, powinieneś zauważyć, że coś nie gra w tle - jest ucięte! Dodając kolejny wiersz do GridLayout’u, nie poprawiliśmy atrybutu rowSpan dla obrazu w tle. Obrazek powinien zajmować 5 wierszy, a nie 4.

 


rest_finder_p2_full


Tworzenie nowego modułu

Udało nam się przygotować główny ekran aplikacji, aby umożliwić użytkownikowi szybsze wyszukiwanie lokali w okolicy. Stwórzmy teraz kolejny ekran, który docelowo będzie zawierał wybór kategorii lokalu, ale teraz przekażemy do niego i wyświetlimy współrzędne.

Za wyświetlanie różnych ekranów w NativeScriptcie z Angularem odpowiada komponent page-router-outlet, który znajduje się w app.component.html i jest tam jedynym elementem. Jest to odpowiednik angularowego komponentu router-outlet, z tą różnicą, że podmienia on zawartość całego ekranu. Do wyświetlania tzw. fragmentów w {N} + Angular używa się router-outlet’ów. Nie komplikujmy na razie sprawy i przejdźmy do utworzenia nowego komponentu.

W lewym panelu “Explorer” klikamy w ikonę menu przy folderze app i dodajemy folder ‘categories’. Z rozwijanego menu przy nowym folderze, dodajemy moduł, komponent (o nazwach categories) oraz moduł categories-routing. Całość ma odpowiadać strukturze modułu home.

Do utworzonego modułu categories-routing kopiujemy zawartość z home-routing.module zmieniając wszystkie nazwy Home na Categories.



 

Musimy teraz zmodyfikować categories.module.ts. Do listy importów dodajemy CategoriesRoutingModule, a do listy deklaracji CategoriesComponent. Zostało nam jeszcze zmodyfikowanie głównego pliku z routingiem aplikacji - app-routing.module.ts.



Zwróć uwagę, że zmieniliśmy także pierwszą linijkę, odpowiadającą za wybór ekranu startowego, przekierowując użytkownika od razu do ekranu categories.

Odświeżając teraz aplikację, powinniśmy zobaczyć pusty ekran z tytułem Categories na górze. Tutaj możesz sprawdzić aktualną strukturę aplikacji.


Ekran ze współrzędnymi

Zbliżamy się do końca! Nasz nowy ekran będzie wyświetlał na razie tylko proste dane. Wykorzystamy do tego strukturę, którą otrzymaliśmy automatycznie po dołączeniu do projektu lokalizacji. W categories.component.html, zamiast komentarza Add your page content here, dodajemy:


Do przekazania danych o lokalizacji wykorzystamy queryParams. Jest to angularowy sposób na przekazywanie danych między routami. W konstruktorze komponentu Categories, wstrzykujemy serwis ActivatedRoute, z którego możemy pobrać przekazane podczas nawigowania dane.


Dane będą przekazywane w formacie JSON string, dlatego wykorzystujemy funkcję JSON.parse() do przekonwertowania ciągu na obiekt.

Pobieranie danych gotowe, teraz musimy je przekazać z naszego głównego ekranu. W app-routing.module.ts przywracamy pierwotne przekierowanie

{ path: "", redirectTo: "/home", pathMatch: "full" }

W pliku home.component.html dodajemy funkcję wywoływaną dotknięciem przycisku Current location



 

Tym razem w konstruktorze komponentu wstrzykujemy serwis RouterExtensions, który rozszerza angularowy serwis Router o dodatkowe funkcjonalności, np. efekty przejścia między ekranami.

Funkcja nawigowania do ekranu kategorii będzie wyglądała następująco:


Definiujemy obiekt navigationExtras, który we właściwości queryParams zawiera nasze dane o lokalizacji, przekonwertowane do formatu JSON string przez funkcję JSON.stringify(). Następnie z serwisu routerExtensions wywołujemy funkcję navigate, która przyjmuje ścieżkę do nawigacji, oraz opcjonalny obiekt navigationExtras. Aby wizualnie urozmaicić aplikację, możemy dodać wspomniany przed chwilą efekt przejścia.


Jeżeli wszystko poszło dobrze to dodaliśmy właśnie funkcję wykrywania lokalizacji i przekazywania informacji do innych ekranów! Tutaj znajdziesz kompletny projekt na Playgroundzie i GitHubie. Masz ochotę poćwiczyć? Utwórz forka projektu i utwórz angularowy serwis, do którego przeniesiesz logikę odpowiadającą za pobieranie lokalizacji.


Kolejna część, wkrótce!
 

Udostępnij:

Stwórzmy coś niesamowitego, poznaj nas i zatrudnij.

Wyceń projekt