Sunteți pe pagina 1din 27

Curs 10

Aplicatii mobile multi-platforma


Xamarin.Forms

Lect. dr. Florina Covaci


Cuprins
• Layouts
• Accesul la date
• Ciclul de viata al aplicatiei
• Xamarin.Esentials
StackLayout
• Organizeaza elementele intr-o stiva – orizontal/vertical
• Proprietatea Orientation specifica directia. In mod implicit orientarea
este verticala
• Este utilizat de obicei pentru a aranja subsectiunile unei
pagini
• Deseori utilizat ca un layout parinte , care contine
alte layout-uri copil
<StackLayout Margin="20">
<Editor Placeholder="Enter your note"
Text="{Binding Text}"
HeightRequest="100" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save"
Clicked="OnSaveButtonClicked" />
<Button Grid.Column="1"
Text="Delete"
Clicked="OnDeleteButtonClicked"/>
</Grid>
</StackLayout>
Grid
• Utilizat pentru a afisa elemente in randuri si coloane
care pot avea dimensiuni absolute sau relative
• Randurile si coloanele sunt specificate cu proprietatile
RowDefinitions si ColumnDefinitions
• Pentru a pozitiona elemente specifice in grid se utilizeaza proprietatile
atasate Grid.Column si Grid.Row
• Pentru ca elementele sa ocupe mai multe randuri sau coloane se
utilizeaza proprietarile atasate Grid.RowSpan si Grid.ColumnSpan
FlexLayout
• Similar cu StackLayout – afiseaza elementele
orizontal/vertical
• Poate sa faca wrap la elementele copil, daca sunt
prea multe si nu incap intr-un singur rand sau coloana
• Permite control granular referitor la marime, orientare,
alinierea elementelor copil
FlexLayout
<FlexLayout Direction="Column" //elem.copil aranjate intr-o
singura coloana
AlignItems="Center" //fiecare elem. va fi centrat orizontal
JustifyContent="SpaceEvenly"> //spatiul liber ramas pe
verticala va fi impartit intre elemente
<Label Text="FlexLayout in Action" />
<Button Text="Button" />
<Label Text="Another Label" />
</FlexLayout>
Accesul la Date
• Cele mai multe aplicatii mobile necesita salvarea
unor date local

• SQLite – database engine

• Pachetul NuGet SQLite.Net


• Adaugam o proprietate in clasa App – database – calea catre fisierul local de tip baza de
date
static TodoItemDatabase database;
public static TodoItemDatabase Database
{
get
{
if (database == null)
{
database = new TodoItemDatabase(

Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalAppl
icationData), "TodoSQLite.db3"));
}
return database;
}
}
• Expunem baza de date ca un singleton – o singura conexiune la baza de date este creata
si este mentinuta deschisa cat timp aplicatia ruleaza, evitand operatia costisitoare de
deschidere/inchidere db la fiecare operatie pe bd
Creare Tabel
• Constructorul primeste ca si parametru calea spre fisierul de tip baza
de date

public TodoItemDatabase(string dbPath)


{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<TodoItem>().Wait();
}
Ciclul de viata al aplicatiei
• Clasa Application contine trei metode care pot fi suprascrise pentru a
raspunde modificarilor din ciclul de viata al aplicatiei
• OnStart – apelata cand aplicatia porneste.
• OnSleep – apelata de fiecare data cand aplicatia se muta in background.
• OnResume – apelata cand se face resume la aplicatie, dupa ce a fost trimisa in
background.
• Nu exista o metoda dedicata pentru terminarea aplicatiei
• In cirmcumstante normale (nu are loc un crash), terminarea aplicatiei
se va realiza din starea Onsleep
Persistarea datelor intre starile aplicatiei
• Clasa Application are o proprietate de tip dictionar:
Properties - poate fi folosita pentru a stoca date intre
diferite stari ale aplicatiei
• Dictionarul utilizeaza o cheie de tip string si salveaza
valoarea unui obiect
• Dictionarul este salvat pe dispozitiv in mod automat si
este repopulat cand se realizeaza repornirea aplicatiei
public partial class App : Application
{ const string displayText = "displayText";
public string DisplayText { get; set; }
public App() { ...}
protected override void OnStart() {
Console.WriteLine("OnStart");
if (Properties.ContainsKey(displayText)) {
DisplayText = (string)Properties[displayText]; }
}
protected override void OnSleep() {
Console.WriteLine("OnSleep");
Properties[displayText] = DisplayText; }
Nu este necesara restaurarea datelor la OnResume deoarece
cand aplicatia se afla in background datele sunt in memorie
Libraria Xamarin.Essentials
• Multe din functionalitatile oferite de aplicatiile mobile se bazeaza pe
noi tipuri de date pot fi colectate de la device-urile mobile (localizare
GPS etc.)
• Xamarin.Essentials ofera un API unic multi-platforma pentru aplicatii
Android, iOS sau UWP, care poate fi accesat din codul comun
• Xamarin.Essentials - NuGet package – il downloadam
• Adaugam directiva: using Xamarin.Essentials;
Clasa Geocoding

• Ofera posibilitatea de a gasi coordonatele pentru o adresa si invers:


gasirea adresei pentru un set de coordonate
• Proprietati: Latitudinea, Longitudinea si Altitudinea
• Altitudinea nu este intotdeauna disponibila – proprietatea Altitude
poate fi null sau 0. Daca este valabila, valoarea indica metri deasupra
nivelului marii
Clasa Geocoding (II)
try
{
var address = "FSEGA Theodor Mihali Cluj-Napoca";
var locations = await Geocoding.GetLocationsAsync(address);

var location = locations?.FirstOrDefault();


if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude},
Longitude: {location.Longitude}, Altitude: {location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
Reverse Geocoding (I)
• Furnizeaza detalii legate de un obiectiv, pentru un set de coordinate furnizat:
• AdminArea - Judet
• CountryCode – Codul tarii (Ex. RO)
• CountryName – Nume tara
• FeatureName – Numele obiectivului de la acele coordinate/ Numarul
• Locality - Localitate
• PostalCode – Cod Postal
• SubAdminArea – Nume municipiu
• SubLocality – Nume Comuna
• SubThoroughfare – Numarul/ Interval Numeric
• Thoroughfare – Strada/Artera
Reverse Geocoding (II)
try
{ var lat = 47.673988; var lon = -122.121513;
var placemarks = await Geocoding.GetPlacemarksAsync(lat, lon);
var placemark = placemarks?.FirstOrDefault();
if (placemark != null) {
var geocodeAddress = $"AdminArea: {placemark.AdminArea}\n" + $"CountryCode:
{placemark.CountryCode}\n" +
$"CountryName: {placemark.CountryName}\n" +
$"FeatureName: {placemark.FeatureName}\n" +
$"Locality: {placemark.Locality}\n" +
$"PostalCode: {placemark.PostalCode}\n" +
$"SubAdminArea: {placemark.SubAdminArea}\n" +
$"SubLocality: {placemark.SubLocality}\n" +
$"SubThoroughfare: {placemark.SubThoroughfare}\n" +
$"Thoroughfare: {placemark.Thoroughfare}\n";
Console.WriteLine(geocodeAddress); }
} catch (FeatureNotSupportedException fnsEx) { // Feature not supported on device }
Clasa Geolocation
• Putem afla coordonatele curente de geolocalizare a dispozitivului
• Pentru a folosi functia de geolocalizare sunt necesare anumite actiuni
de setup specific platformei
• Ex. Android:
• Persmisiunea pentru localizare trebuie setata la proiectul Android
• Daca aplicatia targheteaza >=Android 5.0 trebuie sa specificam ca
applicatia utilizeaza features hardware
Set-up pentru Android
• Se adauga in fisierul AssemblyInfo.cs
[assembly:
UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
[assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
[assembly: UsesFeature("android.hardware.location", Required = false)]
[assembly: UsesFeature("android.hardware.location.gps", Required = false)]
[assembly: UsesFeature("android.hardware.location.network", Required =
false)]

API-ul pentru geolocalizare va cere permisiunea utilizatorului atunci


cand este necesar
Gelocalizare (I)
• Putem gasi ultima locatie cunoscuta a dispozitivului prin apelul metodei
GetLastKnownLocationAsync .
• Este mai rapida decat a executa o interogare noua, dar mai putin exact si poate returna null daca
nu exista locatii salvate in cache

try { var location = await Geolocation.GetLastKnownLocationAsync();


if (location != null)
{ Console.WriteLine($"Latitude: {location.Latitude}, Longitude:
{location.Longitude}, Altitude: {location.Altitude}"); }
}
catch (FeatureNotSupportedException fnsEx)
{ // Handle not supported on device exception }
catch (FeatureNotEnabledException fneEx)
{ // Handle not enabled on device exception }
catch (PermissionException pEx) { // Handle permission exception }
Geolocalizare (II)
• Pentru a afla coordonatele locatiei curente utilizam GetLocationAsync
try {
var request = new
GeolocationRequest(GeolocationAccuracy.Medium);
var location = await
Geolocation.GetLocationAsync(request);
if (location != null) {
Console.WriteLine($"Latitude: {location.Latitude},
Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
} catch (FeatureNotSupportedException fnsEx) { //
Handle not supported on device exception }
Acuratetea geolocalizarii
Lowest Low Medium High

Android 500 500 100-500 0-100

iOS 3000 1000 100 10

UWP 1000-5000 300-3000 30-500 <=10


Distanta intre doua locatii
• Clasa Location defineste metoda CalculateDistance – permite sa
calculam distanta intre doua locatii geografice. Distanta calculata nu ia
in considerare drumurile ci distanta intre doua puncte pe suprafata
Pamantului

Location boston = new Location(42.358056, -71.063611);


Location sanFrancisco = new Location(37.783333, -122.416667);
double miles = Location.CalculateDistance(boston,
sanFrancisco, DistanceUnits.Kilometers);
Clasa Map (I)
• Permite unei aplicatii sa deschida o aplicatie de tip “harti” instalata la o
locatie specificata
• Utilizeaza metoda OpenAsync cu parameterii de tip Location sau Placemark
si optional un paramteru de tip MapLaunchOptions

public class MapTest


{ public async Task NavigateToBuilding25() {
var location = new Location(47.645160, -122.1306032); var
options = new MapLaunchOptions { Name = "Microsoft Building
25" };
await Map.OpenAsync(location, options);
}
}
Clasa Map (II)
• Cand utilizam metoda OpenAsync cu un Placemark este necesara
furnizarea urmatoarelor informatii:
• CountryName
• AdminArea
• Thoroughfare
• Locality
public class MapTest {
public async Task NavigateToBuilding25()
{ var placemark = new Placemark { CountryName =
"United States", AdminArea = "WA", Thoroughfare =
"Microsoft Building 25", Locality = "Redmond" };
var options = new MapLaunchOptions { Name =
"Microsoft Building 25" };
await Map.OpenAsync(placemark, options); } }
Harta- mod navigare
• Daca se apeleaza OpenMapAsync fara parametrul
MapLaunchOptions, harta va fi lansata cu locatia specificata. Optional
putem sa calculam ruta de navigare din pozitia curenta la care se afla
dispozitivul prin setare NavigationMode la MapLaunchOptions
public class MapTest {
public async Task NavigateToBuilding25()
{ var location = new Location(47.645160, -122.1306032);
var options = new MapLaunchOptions { NavigationMode =
NavigationMode.Driving };
await Map.OpenAsync(location, options); }
}
• NavigationMode suporta Bicycling, Driving si Walking

S-ar putea să vă placă și