Professional Documents
Culture Documents
Razvoj Mobilnih Aplikacija Upotrebom Cross-Platform Razvojnog Okruzenja Xamarin
Razvoj Mobilnih Aplikacija Upotrebom Cross-Platform Razvojnog Okruzenja Xamarin
eMPIRICA
U BRČKO DISTRIKTU BIH
ZAVRŠNI RAD
PRVOG CIKLUSA STUDIJA
STUDENT
FARUK SALKIĆ
ii
Abstract
This thesis focuses on analysis of basic functionalities and characteristics of Xamarin
programming development environment, a cross-platform (multi-platform) for mobile
application development (Android, iOS, Windows Phone). The target of this thesis is to
show how much of core (common) code can be used to build the application as well as how
much of the code has to be specifically written for particular platform. Available literature,
other programmers’ experience as well as practical application example were all used to
complete this thesis.
Xamarin allows compilation of core C# code to natively run on all mentioned platforms. By
using the Model-View-ViewModel (MVVM) model of separation of Business logic from
the User's Interface greatly simplifies the use of this tool for building applications.
This thesis will also analyze some other available tools and options for mobile application
developments with as much shared code as feasible, as well as to describe their Pros and
Cons in comparison with Xamarin and in general.
Key Words: Cross-Platform, Native, Xamarin, XAML, C#
iii
Sadržaj
Sažetak ................................................................................................................................... ii
Abstract ................................................................................................................................. iii
Sadržaj .................................................................................................................................. iv
Popis slika ............................................................................................................................. vi
Popis tabela ......................................................................................................................... viii
Popis skraćenica ................................................................................................................... ix
1. Uvod .............................................................................................................................. 1
2. Pojam i razvoj mobilnih aplikacija ................................................................................ 4
2.1. Razvoj nativnih aplikacija za iOS, Android i Windows Phone platforme ............. 4
2.1.1. Android ............................................................................................................ 4
2.1.2. iOS ................................................................................................................... 5
2.1.3. Windows Phone ............................................................................................... 5
2.2. Razvoj cross–platform aplikacija ........................................................................... 6
3. Cross–platform razvojna okruženja............................................................................... 7
3.1. Pristupi kreiranju cross-platform aplikacija ........................................................... 7
3.1.1. Web bazirane cross-platform aplikacije .......................................................... 7
3.1.2. Omotači ........................................................................................................... 8
3.1.3. Hibridne aplikacije .......................................................................................... 8
3.2. Nativne u odnosu na cross-platform aplikacije ...................................................... 8
3.3. Ostala cross-platform rješenja ................................................................................ 9
3.3.1. Apache Cordova .............................................................................................. 9
3.3.2. Appcelerator Titanium ................................................................................... 10
4. Xamarin cross-platform razvojno okruženje ............................................................... 12
4.1. XAML ................................................................................................................... 16
4.1.1. Prednosti i nedostaci XAML-a ...................................................................... 17
4.1.2. Definisanje kôda za svaku platformu ............................................................ 18
4.2. Struktura dokumenata ........................................................................................... 18
4.3. Povezivanje podataka ........................................................................................... 18
4.3.1. Pozivanje konstruktora i metoda sa parametrima iz XAML-a ...................... 19
4.3.2. Pozivanje XAML elemenata iz kôda ............................................................. 20
4.3.3. Događaji i rukovaoci događajima .................................................................. 21
4.4. Gradivni blokovi ................................................................................................... 22
4.4.1. Stranica .......................................................................................................... 22
4.4.1. Pogled ............................................................................................................ 24
iv
4.4.2. Izgled ............................................................................................................. 25
4.4.3. Ćelija.............................................................................................................. 26
4.5. Stilovi .................................................................................................................... 26
4.6. Okidači .................................................................................................................. 27
4.7. Geste ..................................................................................................................... 28
4.7.1. Tapšanje ......................................................................................................... 29
4.7.2. Stezanje.......................................................................................................... 29
4.8. MVVM model....................................................................................................... 30
4.9. Cordova i Appcelerator u poređenju sa Xamarin ................................................. 31
5. Razvoj mobilne aplikacije “Converter” upotrebom Xamarin cross-platform razvojnog
okruženja. ............................................................................................................................ 33
5.1. Kratak pregled instalacije razvojnog okruženja Xamarin ..................................... 33
5.1.1. Hardverski i softverski zahtjevi za instalaciju ............................................... 35
5.2. Struktura projektnog rješenja ................................................................................ 35
5.3. Struktura mobilne aplikacije „Converter“ ............................................................ 36
Zaključak ............................................................................................................................. 42
Bibliografija ......................................................................................................................... 43
Dodatak................................................................................................................................ 45
v
Popis slika
Slika 1.1 Tržište mobilnih operativnih sistema, 2. kvartal 2015.g. ....................................... 2
Slika 1.2 Odnos između broja aplikacija u Android i iOS prodavnicama ............................. 2
Slika 3.1 Odnos između nativnih i cross-platform aplikcija ................................................. 8
Slika 4.1 Arhitektura Xamarina ........................................................................................... 12
Slika 4.2 Struktura Xamarin.Forms projekta ...................................................................... 15
Slika 4.3 Izgled korisničkog sučelja kreiranog upotrebom XAML-a ................................. 16
Slika 4.4 Izgled XAML-a korištenog za korisničko sučelje na slici 4.3. ............................ 16
Slika 4.5 XAML atributi u istoj liniji .................................................................................. 17
Slika 4.6 XAML atributi kao podelementi .......................................................................... 17
Slika 4.7 Definisanje XAML koda za svaku platformu ...................................................... 18
Slika 4.8 Struktura XAML i code-behind dokumenata ....................................................... 18
Slika 4.9 Definisanje sadržaja dugmeta direktno putem atributa ........................................ 19
Slika 4.10 Definisanje sadržaja dugmeta putem povezivanja podataka .............................. 19
Slika 4.11 Dvosmjerno povezivanje podataka .................................................................... 19
Slika 4.12 Pozivanje konstruktora sa parametrima iz XAML-a .......................................... 19
Slika 4.13 Poziv metoda iz XAML-a .................................................................................. 20
Slika 4.14 Pozivanje elementa preko imena iz XAML-a .................................................... 20
Slika 4.15 Pozivanje elementa preko imena iz kôda ........................................................... 20
Slika 4.16 Događaj click u XAML-u ................................................................................... 21
Slika 4.17 Događaj click u kôdu .......................................................................................... 21
Slika 4.18 Događaj tap u XAML-u ..................................................................................... 21
Slika 4.19 Događaj tap u kôdu ............................................................................................ 22
Slika 4.20 ContentPage u XAML-u .................................................................................... 23
Slika 4.21 MasterDetailPage u XAML-u ........................................................................... 23
Slika 4.22 Kreiranje nove NavigationPage stranice u kôdu ................................................ 23
Slika 4.23 XAML kôd stranice TodoListXAML ................................................................ 24
Slika 4.24 TabbedPage u XAML-u ..................................................................................... 24
Slika 4.25 CarouselPage u XAML-u .................................................................................. 24
Slika 4.26 Dodavanje stilova u kôdu ................................................................................... 27
Slika 4.27 Dodavanje stilova u XAML-u ............................................................................ 27
Slika 4.28 Property okidač u XAML-u ............................................................................... 27
Slika 4.29 Data okidač u XAML-u ..................................................................................... 28
Slika 4.30 Event okidač u XAML-u .................................................................................... 28
Slika 4.31 Multi okidač u XAML-u .................................................................................... 28
Slika 4.32 Događaj Tap u XAML-u .................................................................................... 29
Slika 4.33 Događaj Tap u kôdu ........................................................................................... 29
Slika 4.34 Kreiranje instance PinchGestureRecognizer klase u kôdu ................................ 29
Slika 4.35 Kreiranje instance PinchGestureRecognizer klase u XAML-u ......................... 29
Slika 4.36 Kreiranje metode za rukovanje događajem ........................................................ 29
Slika 4.37 Kreiranje klase i metoda za rukovanje događajem ............................................. 30
Slika 4.38 “Omotavanje“ kôda oko elementa ...................................................................... 30
Slika 4.39 Interakcija unutar MVVM modela ..................................................................... 30
Slika 5.1 Struktura projektnog rješenja ............................................................................... 35
Slika 5.2 Primjer klase App.cs ............................................................................................. 36
Slika 5.3 Korisničko sučelje na Android i Windows phone emulatoru............................... 36
Slika 5.4 XAML kôd za korisničko sučelje mobilne aplikacije “Converter“ ..................... 38
vi
Slika 5.5 Struktura mobilne aplikacije “Converter“............................................................ 39
Slika 5.6 Converter .............................................................................................................. 39
Slika 5.7 Pritisak na bilo koje dugme .................................................................................. 40
Slika 5.8 Promjena pri odabiru druge mjerne jedinice ........................................................ 40
Slika 5.9 Reakcija pri pokušaju promjene predznaka mjerne jedinice ................................ 40
Slika 5.10 Primjer async metode ......................................................................................... 41
vii
Popis tabela
Tabela 3.1 Usporedba cross-platform i nativnih aplikacija................................................... 9
Tabela 4.1 Uslovi za razvoj aplikacija................................................................................. 13
Tabela 4.2 Pogledi ............................................................................................................... 25
Tabela 4.3 Ćelije .................................................................................................................. 26
Tabela 4.4 Poređenje različitih Cross-platform rješenja ..................................................... 31
Tabela 5.1 Pregled Xamarin opcija ..................................................................................... 34
viii
Popis skraćenica
3G Treća generacija mobilne telekomunikacijske tehnologije
4G Četvrta generacija mobilne telekomunikacijske tehnologije
API Application Process Instruction
ARM Acorn RISC Machine
ASCII American Standard Code for Information Interchange
B2C Business To Customer
CSS Cascading Style Sheets
GPS Global Positioning System
GSM Global System for Mobile Communications
GUI Graphic User Interface
HTML HyperText Markup Language
IDE Integrated Development Environment
MVVM Model-View-ViewModel
OS Operating System
PDA Personal Digital Assistant
SDK Software Development Kit
SIM Subscriber Identity Module
UI User Interface
Wi-Fi Bežična internet mreža
XAML Extensible Application Markup Language
XML Extensible Markup Language
ix
1. Uvod
Razvojni put mobilnih uređaja je poprilično dug i interesantan, obzirom da su prvi mobilni
telefoni bili tek jednostavne naprave za mobilnu komunikaciju koju su ostvarivali u obliku
telefonskih poziva i slanjem kratkih tekstualnih poruka, a danas su postali mali kompjuteri
ili kako se popularno nazivaju: pametni telefoni (eng. smart phones). Revoluciju u razvoju
mobilnih telefona je pokrenuo Apple sa svojim prvim pametnim telefonom, iPhone 1,
izdanim 2007. godine. Pametni telefoni su postojali i prije toga, na operativnom sistemu
Windows CE ali je iPhone dao najveći doprinos popularizaciji istih. Otprilike godinu dana
kasnije (2008. godine) je nastao i prvi Android telefon. Android, kao operativni sistem (OS),
je u početku bio manje popularan i kasnio par godina za iOS-om ali je danas daleko ispred
ostalih.
Tržište pametnih telefona je već odavno prešlo iz tržišta koje je u razvoju i koje obećava, u
potpuno dominantno tržište informatičke tehnologije. Statistički podaci [1] pokazuju rast
isporuke pametnih telefona od 28,4% u periodu 2013 - 2014. godina. Međutim, podatak o
odnosu između isporučenih pametnih telefona i računara [2] od preko 4,3:1 u korist pametnih
telefona stvara pravu sliku o globalnom trendu u kojemu dominiraju ovi uređaji.
Životni ciklus aplikacije za pametni telefon i tablet je, očekivano, dosta kraći od životnog
ciklusa aplikacije za računare. Ovo je direktna posljedica težnje i potrebe da se mobilne
aplikacije brzo i učinkovito adaptiraju na potrebe kako korisnika tako i tržišta. Ovakav,
uslovno rečeno, rapidan razvoj i prodor novih, te unaprijeđenje postojećih aplikacija zahtjeva
efikasne alate za razvoj mobilnih aplikacija i njihovo plasiranje na tržište.
Kao i uvjek kada se radi o informacionim tehnologijama, rast tržišta pametnih telefona i
tableta, kako u obimu tako i u brzini, je propraćen, pa čak i prevaziđen, rastom tržišta
odgovarajućih mobilnih aplikacija. Iako postoji širok spektar dostupnih aplikacija
namjenjenih svim vrstama korisnika, veliki broj ih je namjenjen običnim korisnicima koji
na neki način koriste usluge biznisa tj. radi se o poslovnim aplikacijama za korisnike (eng.
Business To customer – B2C). Pojedine aplikacije se razvijaju i stavljaju u upotrebu u roku
od svega par dana, što zahtjeva efikasne alate za razvoj aplikacija.
Statistički podaci za 2014 [3] pokazuju da su tri dominantne platforme: Android sa 82,8%
učešća u tržištu, iOS sa 13,9% i Windows sa 2,6%. Preostale platforme (uključujući
BlackBerry, Symbian, Fire OS i druge) zajedno učestvuju sa tek nekih 0,7% na globalnom
tržištu pametnih telefona i tableta.
1
0,30%
2,60% 0,40%
13,90%
Android
iOS
Windows Phone
BlackBerry OS
Others
82,80%
1800000
1600000
1400000
1200000
1000000
800000
600000
400000
200000
0
2012 2013 2014 2015
Android iOS
3
2. Pojam i razvoj mobilnih aplikacija
Razvoj aplikacije za jednu ili više mobilnih platformi je uslovljen poznavanjem razvojnog
okruženja za svaku od pomenutih platformi. Razvojni jezici za pomenute platforme su
različiti: Objective-C, Visual C#, Visual Basic, Java i dr. Takođe su različita i razvojna
okruženja koja se koriste za izradu aplikacija. Iako su svi programski jezici za izradu
mobilnih aplikacija objektno orijentisani i vuku korijene iz programskog jezika C, ipak imaju
različite sintakse zbog čega se zahtjeva detaljno poznavanje svakog programskog jezika za
učinkovit rad.
Razvoj mobilnih aplikacija upotrebom cross-platform pristupa gdje se aplikacija razvija
upotrebom samo jednog programskog jeyika (npr. C# ili JavaScript) ili kombinacijom
nekoliko programskih jezika (HTML5, JavaScript i CSS3) rješava gore pomenuti problem.
2.1.1. Android
Android je operativni sistem trenutno u vlasništvu Google Inc. a koji je baziran na Linux
kernelu. Originalno Android je kreiran i razvijan od strane Android Inc. koji je prešao u
vlasništvo Google Inc. 2005. godine a sam operativni sistem se pojavio na tržištu 2007.
godine [6].
Android applikacije se razvijaju u programskom jeziku Java. Aplikacije se orginalno
razvijaju u Android Studiu ali se sa odgovarajućim dodatkom (Android Programer Tools)
mogu razvijati i u Java razvojnim okruženjima kao što su NetBeans i Eclipse.
Sve aplikacije kreirane i instalirane na Android OS-u imaju ista prava bez obzira da li su
razvijene i instalirane naknadno (eng. after-market) ili su došle kao dio OS-a (eng. core
4
aplications). Takođe, sve aplikacije se izvršavaju unutar svojih virtualnih prostora (npr.
Dalvik VM) što znači da su izolirane i nemaju pristup podacima koji se tiču drugih aplikacija,
izuzev ako nisu dobile posebna i eksplicitna ovlaštenja u toku instalacije da pristupe tim
podacima.
Android je plasiran na tržište pod licencom “otvorenog tipa” (eng. open source). Iako je
open source i besplatan mnogi proizvođači pored samog OS-a uključuju i određene
vlasničke aplikacije (npr. LG Backup & Restore aplikacija).
Android OS je moguće instalirati na sve mobilne uređaje koji svojom infrastrukturom
podržavaju ovaj operativni sistem.
2.1.2. iOS
iOS je mobilni operativni sistem kreiran od strane Apple Inc. koji je pušten u upotrebu 2007.
godine kao operativni sistem za prvu generaciju iPhone telefona i iPod muzičkih uređaja.
Ovo je operativni sistem koji je potpuno u vlasništvu Appl Inc. i radi isključivo sa Apple
mobilnim uređajima [7].
iOS je od nastanka pored pomenutih iPhone i iPod uređaja iskorišten i za iPad prenosne
tablet uređaje. Ovaj sistem je nastao direktno od MacX operativnog sistema za Apple
kompjutere, a koji se dalje bazira na Unix operativnim sistemima.
iOS aplikacije se razvijaju u dva programska jezika: Objective-C, stariji jezik koji je još
uvjek standard za razvoj ovih aplikacija, i Swift, noviji programski jezik kreiran od strane
Apple Inc. Kao razvojno okruženje se koristi Xcode uz iOS paket za razvoj softvera (eng.
Software Develpment Kit – SDK) i obaveznu upotrebu Mac računara na kome se vrši
kompiliranje. Pokretanje i testiranje aplikacija na iOS emulatorima, koji dolaze u paketu sa
Xcode, je besplatno i neograničeno. Međutim, stavljanje aplikacije na upotrebu korisnicima
i instaliranje na fizičke uređaje spada pod licencirane aktivnosti. Takve aktivnosti zahtjevaju
da se plati određena vrsta novčane naknade kao i da Apple ima mogućnost kontrole i
odobravanja aplikacije za postavljanje u iTunes prodavnicu.
5
2.2. Razvoj cross–platform aplikacija
Pojednostavljeno gledano, za razvoj jedne aplikacije za više platformi poslovni subjekt bi
morao zadovoljiti jedan od sljedećih uslova:
6
3. Cross–platform razvojna okruženja
Cross-platform kao pojam se počeo javljati tek u kasnim 1970-tim godinama. Prije toga
pojam kao takav nije postojao. Čak štaviše, Unix kao osnovni operativni sistem je morao biti
posebno prilagođavan svakoj promjeni u hardverskoj konfiguraciji ili platformi. Ukoliko se
hardver mjenjao, morao se mjenjati i sam Unix u cjelosti i prilagođavati novim uređajima.
Razvojem računarske tehnologije javila se i potreba da se uradi nešto po tom pitanju, tako je
1976. godine Unix predstavio make i Makefiles. Make i Makefiles je bio proces pametnog
kompiliranja izvornih fajlova i prosljeđivanja komandnih linija kompileru. Nakon toga
rapidan rast u kompjuterskoj industriji je vodio tome da se razvijalo sve više softverskih
rješenja koja su bila komaptibilna sa različitim platformama što je u neku ruku postavilo
osnove za cross-platform rješenja.
Stvarni razvoj cross-platfrmi je omogućen razvojem X11 sistema 1980-tih godina, koji je
omogućio osnovni radni okvir (eng. framework) za Grafičko Korisničko Sučelje (eng.
Graphic Users Insterface – GUI) radnu okolinu. Motif, jedan od prvih widget alata koji je
kao osnovu imao X11, u kombinaciji sa samim X11 je omogućio podršku za razvoj cross-
platform rješenje za sve popularne platforme.
Programski jezici kao što su C, C++ i Java su omogućili da se kôd piše jednom i, pomoću
ponovnog kopmiliranja za svaku platformu posebno, koristi na različitim platformama. Na
primjer Java programi se bez izmjena pokreću na svim platformama koje podržavaju JRE za
izvođenje programa.
Nakon toga je izvedeno nekoliko više-ili-manje uspješnih pokušaja da se napravi razvojno
okruženje koje bi zadovoljilo potrebu da se kôd piše jednom i instalira na sve (ili više)
platforme kao što su: Swing (1997, Sun Microsystems), Silverlight (2007, Microsoft) i
druga. Međutim, Swing je u praksi odbačen, dok je Silverlight još uvjek u upotrebi ali samo
kod razvoja Windows i Windows Phone aplikacija.
Što se tiče razvoja mobilnih tehnologija, iste je pratio i razvoj platformi koje su esencijalno
različite. To je uvelo i pojam aplikacija (Apps) koji su ustvari mali programi koji koriste
sposobnosti mobilnih uređaja kako bi korisniku omogućili nove usluge i mogućnosti. Razvoj
cross-platform rješenja je utoliko važniji uzimajući u obzir broj i različitost mobilnih
platformi (Android, iOS, Windows Phone, Symbian, Fire OS, Bada, itd.)
3.1.2. Omotači
Omotači (eng. wrappers) se još zovu i školjke (eng. shells). Ovo je tip cross-platform
aplikacija kod kojih se za razvoj nativnih aplikacija koriste web alati (HTML5, JavaScrip,
CSS) a koji se zatim umotavaju (wrap) i pakuju kao nativne aplikacije za različite platforme.
Neki od alata koji su specijalizovani za izradu ove vrste aplikacija su Adobe Cordova
(PhoneGap), Trigger.io.
8
Tabela 3.1 Usporedba cross-platform i nativnih aplikacija
Cross-platform Nativne
Iz slike 3.1 i tabele 3.1 je vidljivo da nativne aplikacije imaju prednost u kvaliteti i brzini
izvođenja, dok su one kreirane cross-platform pristupom jeftinije, brže realizovane,
prenosive na različite platforme i skoro jednako funkcionalne kao i nativne.
Što se tiče poređenje između samih cross-platform rješenje, tu glavnu ulogu igraju sljedeći
faktori: cijena alata, proširivost alata, da li aplikacija ima pristup svim funkcionalnostima ili
ne, mogućnosti upotrijebljenog kôda. Neka od rješenja i međusobni odnosi su pomenuti u
poglavlju 4.9.
9
Iako je trenutno ime alata Apache Cordova, njegovo prijašnje ime PhoneGap je svakako
jedno od najpoznatijih u programerskoj zajednici. Sam alat je nastao kao kreacija kompanije
“Nitobi” koja je kao kompanija naknadno bila donirana “Apache Software Foundation”
nakon čega je promjenjeno i ime. Vlasništvo je još jednom promjenjeno i sada cjelokupan
projekat pripada kompaniji “Adobe”.
Prednosti ovog razvojnog okruženja i njegovih kreiranih aplikacija uključuju [11]:
Cordova aplikacije se instaliraju na isti način kao i nativne aplikacije i kao takve ih
je moguće lako naći u prodavnicama aplikacija.
Besplatna verzija je u principu i osnovna verzija bez niza sofisticiranih alata koje
omogućavaju PhoneGap Build (Adobe) ili Icenium (Telerik).
Open-source je takođe i prednost, jer postoji veliki broj programera koji doprinose
razvoju ovog alata i dodataka za isti, ali i nedostatak jer isti ti dodaci mogu biti
zastarjeli i bez odgovarajuće podrške za nove platforme.
Dodaci su dobro rješenje i funkcionišu, alisve dok se mogu naći odgovarajući dodaci
programu. Međutim, ukoliko isti ne postoje ili ne zadovoljavaju potrebe aplikacije
onda je potrebno da programeri koji rade na aplikaciji budu dovoljno sposobni da
urade neke svoje dodatke, što u neku ruku nema svrhe jer je u tom slučaju potrebno
imati nekoga ko je specijalizovan za određenu platformu tj. nekoga čije znanje
prevazilazi samo HTML5, JavaScript i CSS.
Upotreba JavaScripta kako bi se napravio isti kôd za sve platforme uveliko pomaže
kod iskorištenja programerskih vještina kod postojećih zaposlenika.
Postoji plaćeno tržište za dodatne usluge kao što je: app analytics, Backend-as-a-
Service (BaaS), tržište za programske komponente proizvedene od strane drugih
vendora.
Nedostaci ovog razvojnog okruženja su [11]:
Normalizacija korisničkog sučelja na svim platformama znači da je dio ili cijeli kôd
ustvari vlasnički i samim time zahtjeva određeno vrijeme kako bi ga tim koji radi na
razvoju aplikacija savladao. To znanje se obično može jako malo iskoristiti van
samog Appceleratora.
11
4. Xamarin cross-platform razvojno okruženje
Xamarin (čita se “Zamarin”) kao jedno od dostupnih cross-platform rješenja je u suštini
kolekcija alata i radnih okvira (eng. frameworks) čiji je jedini zadatak omogućiti da se Visual
C# i .NET upotrijebe za izradu Android i iOS aplikacija. Xamarin kao softversko rješenje je
proizvod i vlasništvo kompanije Xamarin a čiji su idejni tvorci i osnivači isti inženjeri koji
su kreirali i Mono, MonoTouch i Mono za Android a koji su cross-platform implementacija
Common Language Infrastructure (CLI) i Common Language Specifications poznate i kao
Microsoft .NET [12].
Zajedno, Xamarin i Mono omogućavaju upotrebu Visual C# i .NET na Linux, iOS, Mac i
Android platformama uz pomoć alata Mono, Xamarin.iOS, Xamarin.Mac i
Xamarin.Android, respektivno [12].
Xamarin sadrži niz kompilacijskih alata namjenjenih kompilaciji Visual C# kôda i .NET-a.
Kod Android platforme kompilacija kôda se radi kada za to dođe vrijeme tj. Just-In-Time
(JIT), gdje se Visual C# kôd kompilira u bytecode (Intermediate Language - IL) uz pristup
Java kôdu i frameworku koji je trenutno u upotrebi, a koji se dalje kompilira u mašinski kôd
kada je aplikacija pokrenuta na uređaju.
Međutim kod iOS platforme postupak je nešto drugačiji. Naime, Apple ne dozvoljava da
bilo kakav runtime bude instaliran kroz njihovu prodavnicu aplikacija, zbog čega se
kompilacija Visual C# kôda u nativni ARM (eng. Acorn RISC Machine) binarni kôd izvodi
na način da se Visual C# kôd unaprijed uvezuje sa upotrijebljenim .NET bibliotekama
(uključujući i neophodne Objective-C biblioteke). Ovaj proces je poznat i kao Ahead-of-
Time ili AOT. Time se izbjegava nedozvoljena upotreba runtimea kroz iTunes store. Slika
4.1 prikazuje opisane procese kompilacije kôda za slučaj Android i iOS platforme.
Android – Razvoj aplikacija za Android se može vršiti bilo na Windows računaru ili
na Mac-u. Uslov je da su instalirani Java i Android SDK. Ovi alati su potrebni kako
bi se izvršilo testiranje na ugrađenim emulatorima. Takođe je moguće izvršiti i
pokretanje aplikacije na fizičkom Android uređaju koji je direktno (USB ili
BlueTooth) povezan sa računarom i na kojem je omogućen USB debugging. Ova
vrsta testiranja na fizičkom uređaju ne zahtjeva posebnu dozvolu, međutim
distribucija putem neke od prodavnica je stvar licenciranja a moguće i naplate.
iOS
Android
Windows Phone
14
stiliranje) se mogu dodavati u sam XAML ili programatično tj. putem Visual C# kôda u .cs
formi. Izgled samog korisničkog sučelja kao i cjelokupne aplikacije je moguće vidjeti tek
nakon izrade projekta koristeći jednu od dostupnih opcija: debug ili release bilo na
emulatoru (iOS, Android i Windows Phone) ili na stvarnom fizičkom uređaju, legalno
posmatrano na Android i Win Phone bez posebnih ograničenja a iOS tek uz kupljenu licencu
i odobrenje od strane Apple-a.
Xamarin kao kompletno programsko rješenje takođe nudi opciju razvoja nativnih aplikacija,
aplikacija za samo jednu platformu, preko podrške za grafički preglednik koji je jako
koristan kod vizualizacije projekta i pojednostavljenog drag-and-drop sistema razvoja.
U osnovi Xamarin.Forms aplikacija sadrži tri projekta za mobilne platforme i jedan projekt
za zajednički kôd [17], Slika 4.2.
15
2. Xamarin.Forms.Core i Xamarin.Forms.Xaml su biblioteke koje dalje
implementiraju Xamarin.Forms API. Xamarin.Forms. Core potom, koristeći neku
od biblioteka specifičnih za određenu platformu vrši mapiranje tj. prevodi
(rendering) objekate iz Xamarin.Forms korisničkog sučelja u objekte koji
odgovaraju specifičnim platformama.
3. Nakon toga aplikacija ide na kompiliranje (u slučaju iOS i Androida, obzirom da
Visual C# nije nativni programski jezik za ove dvije platforme) uz pomoć
Xamarin.iOS i Xamarin.Android biblioteka. Jednom kompilirane ove aplikacije po
potrebi upućuju poziv odgovarajućim API-ima.
4.1. XAML
XAML je Proširivi Jezik za Označavanje Aplikacija (eng. Extensible Application Markup
Language) dizajniran od strane Microsofta koji kao osnovu ima XML(eng. Extensible
Markup Language) i glavna mu je namjena kreiranje instanci i inicijalizacija objekata. Slike
4.3 i 4.4 prikazuju korisničko sučelje aplikacije, izrađene u XAML-u [18].
Hijerarhijska struktura XML-a kao osnove daje bolji uvid u izgled aplikacije.
17
4.1.2. Definisanje kôda za svaku platformu
Ukoliko je to potrebno, XAML dopušta da se definiše poseban kôd za svaku platformu da
bi se sadržaj ispravno prikazao na svim platformama. Svaka platforma može imati neke svoje
posebne zahtjeve i uslove za pojedine elemente. Kako bi se udovoljilo svim posebnim
zahtjevima na najjednostavniji način koristi se <OnPlatform> opcija u XAML-u za pojedine
atribute kao u primjeru na slici 4.7.
1 <StackLayout>
2 <StackLayout.VerticalOptions>
3 Center
4 </StackLayout.VerticalOptions>
5 <StackLayout.HorizontalOptions>
6 Center
7 </StackLayout.HorizontalOptions>
8 <StackLayout.IsEnabled>
9 True
10 </StackLayout.IsEnabled>
11 <StackLayout.Padding>
12 <OnPlatform x:TypeArguments="Thickness"
13 iOS="10, 0, 10, 0"
14 Android="0, 10, 0, 0"
15 WinPhone="0, 0, 10, 10" />
16 </StackLayout.Padding>
17 <Label Text="Label1"></Label>
18 <Label Text="Label2"></Label>
19 </StackLayout>
Slika 4.7 Definisanje XAML koda za svaku platformu
Takođe ovo isto je moguće uraditi i upotrebom Visual C# kôda, u tu se svrhu koristi klasa
pod imenom Device. Programski je moguće utvrditi na kojoj platformi se izvršava kôd i
odatle odabrati vrijednosti ili objekte koji su prilagođeni toj platformi.
18
Xamarin.Forms instalira automatske event handlere koji rukuju prenosom vrijednosti iz
jednog elementa u drugi kako se to ne bi moralo raditi ručno kôdirati [20].
Dakle, povezivanje podataka se vrši između atributa dva proizvoljna elementa gdje je jedan
izvor (source) a drugi cilj (target). Kako bi sve to funkcionisalo moraju se zadovoljiti dva
uslova. Prvi je da se postave BindingContext atributi ciljanog elementa tako da pokazuju na
izvor a drugi je da se pozove SetBinding metod na ciljani element kako bi se povezali atributi
tog elementa sa atributima izvornog elementa [21]. Pojednostavljeno, BindingContext je
putokaz od cilja ka izvoru a SetBinding je metod koji pokreće samo povezivanje. Ovaj metod
može biti eksplicitno izveden ili automatski generisan tokom kompiliranja na osnovu
postavljenih putokaza.
Jednostavan primjer povezivanja podataka je dat na slikama 4.9 i 4.10.
1 <Button Content="Text"/>
Slika 4.9 Definisanje sadržaja dugmeta direktno putem atributa
1 Public class MyButton ()
2 {
3 Public string ButtonText { get; set; }
4 }
5 <Button Content="{Binding Path=ButtonText}"/>
Slika 4.10 Definisanje sadržaja dugmeta putem povezivanja podataka
Povezivanje podataka može biti jednokratno (OneTime), jednosmjerno (OneWay) ili
dvosmjerno (TwoWay). Standardne postavke su jednosmjerne dok se za dvosmjerne ili
jednokratne mora eksplicitno naznačiti kao u primjeru na slici 4.11 gdje se dugme Favorite
i odgovarajući checkbox međusobno simultano aktiviraju ili deaktiviraju:
1 <CheckBox IsChecked="{Binding isFavorite, Mode=TwoWay}"/>
1 <object
2 <x:Arguments>
3 Jedan_ili_više argumenata
4 </x:Arguments>
5 </object>
Slika 4.12 Pozivanje konstruktora sa parametrima iz XAML-a
19
Dok se za poziv metoda još dodatno koristi i x:FactoryMethod direktiva sa ili bez
x:Argument direktive kao na slici 4.13.
1 <object x:FactoryMethod="imeMatode"...>
2 <x:Arguments>
3 Jedan_ili_više argumenata
4 </x:Arguments>
5 </object>
Slika 4.13 Poziv metoda iz XAML-a
Naravno, broj i tip argumenata u XAML-u mora odgovarati broju i tipu elemenata u
konstruktoru ili metodi. XAML omogućava da ti argumenti budu tipa x:String, x:Int32,
x:Double, x:DateTime, x:Boolean itd.
Ime elementa mora početi malim ili velikim slovom ili donjom crticom iz ASCII
skupa znakova.
Ime mora biti jedinstveno (ime se može pojavljivati samo jednom u datom
dokumentu).
20
deklarisan u samom kôdu. Treba pomenuti da su ta polja po defaultu deklarisana kao private
i može im se pristupiti samo iz trenutne klase dok ostale klase nemaju pristup.
21
A programski bi to bilo riješeno na način sličan ovome:
1 var tapGestureRecognizer = new TapGestureRecognizer();
2 tapGestureRecognizer.Tapped += (s, e) => {
3 LoadTime();
4 };
5 Time_img.GestureRecognizers.Add(tapGestureRecognizer);
Stranica (Page)
Raspored (Layout)
Pogled (View)
Ćelija (Cell)
4.4.1. Stranica
Stranica (eng. Page) je vizuelni element koji organizuje sadržaj koji korisnik vidi na ekranu
uređaja u nekom trenutku. Xamarin.Forms Stranica je u suštini apstrakcija Activity elementa
u Android platformi i View Controller elementa u iOS platformi [24]. Aplikacija mora
sadržavati barem jednu ali može i više stranica. U bilo kojem trenutku u aplikaciji može biti
aktivna jedna ili više stranica, ovisno o načinu na koji se vrši pozivanje i aktiviranje drugih
stranica.
Na različitim platformama stranice se različito i nazivaju te tako imamo Activity,
ViewController i Page na Android, iOS i Windows Phone platformama, respektivno. Ipak,
iako se tako zovu, vrijedi napomenuti da Xamarin.Forms stranice nisu aktivnosti kako se da
naslutiti prema imenu za Android platformu.
Naravno postoji nekoliko vrsta pomenutih stranica a od namjene zavisi i koje će biti
upotrijebljene:
ContentPage,
MasterDetailPage,
NavigationPage,
TabbedPage,
22
CarouselPage,
ContentPage
Osnovna i najjednostavnija stranica koja prikazuje samo jedan pogled. Najčešće ova stranica
sadrži neki od kontejnera kao što su StackLayout, GridLayout ili ScrollView. Ova stranica
može sadržavati samo jedno dijete, dakle sve što se nalazi na toj stranici mora biti unutar
oznaka <ContentPage>. Primjer je dat na slici 4.20.
1 <?xml version="1.0" encoding="utf-8" ?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4 x:Class="Converter_X.Main">
5 <Grid Grid.Row="0">
6 ...
7 </Grid>
8 </ContentPage>
Slika 4.20 ContentPage u XAML-u
MasterDetailPage
Ovo je stranica koja upravlja sa dva nivoa informacija:
Master stranica koja rukuje podacima na visokom nivou (npr. lista naslova knjiga)
Detail stranica koja rukuje podacima tj. detaljima o informacijma koje se nalaze u
Master pageu (npr. sažetak za svaki pojedini naslov iz liste knjiga).
Primjer je dat na slici 4.21.
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <MasterDetailPage
3 xmlns="http://xamarin.com/schemas/2014/forms"
4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
5 x:Class="MasterDetailSample">
6 <MasterDetailPage.Master>
7 <ContentPage>
8 ...
9 </ContentPage>
10 </MasterDetailPage.Master>
11 <MasterDetailPage.Detail>
12 <ContentPage>
13 ...
14 </ContentPage>
15 </MasterDetailPage.Detail>
16 </MasterDetailPage>
Slika 4.21 MasterDetailPage u XAML-u
NavigationPage
Stranica čiji je osnovni zadatak da se brine o koriničkom iskustvu tj. vrši navigaciju između
hrpe drugih stranica (najčešće tipa ContentPage). Primjer kreiranja jedne takve stranice u
XAML-u je nešto malo drugačiji i dat je na slikama 4.22 4.23.
1 new NavigationPage (new TodoListXAML);
Slika 4.22 Kreiranje nove NavigationPage stranice u kôdu
23
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 x:Class="TodoXAML.TodoListXAML"
5 Title="TodoXAML">
6 <ListView x:Name="listView" ItemSelected="OnItemSelected">
7 ...
8 </ListView>
9 </ContentPage>
Slika 4.23 XAML kôd stranice TodoListXAML
TabbedPage
Za razliku od ContentPage koja može imati samo jedno dijete ova vrsta stranice se zove i
MultiPage i može imati više djece tj. podstranica koje se unutar TabbedPage prikazuju kao
tabovi na vrhu ekrana. Primjer u XAML-u na slici 4.24.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <TabbedPage
3 xmlns="http://xamarin.com/schemas/2014/forms"
4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
5 <TabbedPage.Children>
6 <ContentPage Title="Page 1" Icon="icon1.png" />
7 <ContentPage Title="Page 2" Icon="icon2.png" />
8 </TabbedPage.Children>
9 </TabbedPage>
Slika 4.24 TabbedPage u XAML-u
CarouselPage
Donekle slična TabbedPage, ova vrsta stranica je takođe MultiPage s tom razlikom da se
navigacija između stranica-djece vrši povlačenje prsta preko ekrana (swipe) sa jedne na
drugu stranu. Primjer u XAML-u na slici 4.25.
1 <CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XAMLExample1.MyPage">
2 <ContentPage>
3 ...
4 </ContentPage>
5 <ContentPage>
6 ...
7 </ContentPage>
8 </CarouselPage>
Slika 4.25 CarouselPage u XAML-u
4.4.1. Pogled
Pogled (eng. View) je vizuelna kontrola (widget) koja prezentuje informacije i omogućava
korisniku interakciju sa aplikacijom. Ove kontrole nasljeđuju atribute View klase [24].
Definisano je 19 takvih kontrola (pogleda) koje su date u tabeli 4.2:
24
Tabela 4.2 Pogledi
Vrsta Opis
ActivityIndicator Vizuelna kontrola koja pokazuje da se nešto događa bez detalja o samom
događaju.
BoxView Pogled koji daje puni pravougaonik čije su defaultne dimenzije 40x40.
Koristan za postavljanje slika i sličnih elemenata kod testiranja.
Button Dugme koje reaguje na klik.
DatePicker Pogled koji omogućava odabir datuma sa posebnom kontrolom za odabir
datuma.
Editor Kontrola koja može obrađivati višestruke linije teksta.
Entry Kontrola koja obrađuje samo jednu liniju teksta. Korisna kod npr. unosa
korisničkog imane i lozinke.
Image Pogled koji sadrži sliku.
Label Pogled koji pokatuje jednu ili više linija teksta i koji se ne može obrađivati.
ListView Pogled koji prikazuje grupu podataka u vidu vertikalne liste.
OpenGLView Pogled za prikazivanje OpenGL sadržaja. Primjenjiv samo kod Androida i iOS-
a.
Picker Kontrola za odabir elemnata u listi (slično drop down maniju) sa posebnom
kontrolom za odabir elementa.
ProgressBar Kontrola koja pokazuje progres.
SearchBar Kontrola koja omogućava pretraživanje.
Slider Kontrola koja omogućava unos linearne vrijednosti.
Stepper Kontrola koja omogućava unos diskretne vrijednosti ograničene na neki
skup.
Switch Kontrola koja omogućava upotrebu prekidača.
TableView Pogled koji sadrži ćelije tabele.
TimePicker Pogled koji omogućava odabir vremena sa posebnom kontrolom za odabir
vremena.
WebView Pogled koji prikazuje HTML sadržaj.
4.4.2. Izgled
Izgled predstavlja poseban tip pogleda (View) koji ugnježđuje kontrole [24]. Glavna uloga
mu je da postavlja, pozicionira i određuje veličinu elementa-djece (kontrola) koji se nalaze
unutar stranica te ih organizuje u neku logičku strukturu.
Postoji više vrsta Izgleda:
25
GridLayout – Izgled koji elemente raspoređuje unutar defisane rešetke (eng. grid) tj.
u redove i kolone.
ContentView – Element koji se sastoji od samo jednog pogleda i kao takav nema
neke velike upotrebe.
Frame – Element koji sadrži samo jedno dijete i ima neke opcije za pravljenje okvira.
Uobičajene postavke razmaka između okvira i sadržaja (eng. padding) kod ovog
elementa su 20.
4.4.3. Ćelija
Ćelija (eng. Cell) je opisni element koji određuje šablon po kojemu se kreira vizuelni
element. Ćelija je element dizajniran kako bi bio pridodan u ListView ili TableView kontrole
[24].
Postoji nekoliko vrsta ćelija koje su i prikazane u tabeli 4.3.
Tabela 4.3 Ćelije
Vrsta Opis
EntryCell Ćelija sa labelom i poljem za unos jedne linije
teksta.
SwitchCell Ćelija sa labelom i uključi-iskluči prekidačem.
Text Cell Ćelija sa primarnim i sekundarnim tekstom.
ImageCell Tekstovna ćelije koja takože uključuje i sliku.
4.5. Stilovi
Stiliranje korisničkih kontrola u Xamarin.Forms je omogućeno na dva načina: upotrebom
Visual C# jezika u code-behind dokumentu ili unutar XAML dokumenta kao što je prikazano
na slikama 4.26 i 4.27. Ograničenja u odnosu na nativne aplikacije naravno postoje. Stilovi
(eng. Styles) moraju biti definisani za određeni tip kontola (dugmad, labele i sl.) i postavljaju
vrijednosti onih atributa koji su dostupni za tu vrstu kontrola. Postavljanje atributa koji nisu
definisani u Xamarin.Forms je moguće primjenom stilova na određene platforme.
Stilovi mogu biti primjenjeni selektivno, upotrebom ključa (key) kao i globalno (implicitno)
kada se primjenjuju na određeni tip kontrola. Stil se može dodati direktno kontroli (inline)
ili se može dodati u tzv. ResourceDisctionary na nivo stranice ili čak i aplikacije.
Ukoliko je potrebno uraditi stil koji nije dopušten unutar cross-platforme isti se može
definisati za svaku platformu pojedinačno.
Postoje već predefinisani stilovi u biblioteci Device.Styles [25]:
BodyStyle
CaptionStyle
ListItemDetailTextStyle
26
ListItemTextStyle
SubtitleStyle
TitleStyle
1 var mylabel = new Label {
2 Text = "This uses TitleStyle",
3 Style = Device.Styles.TitleStyle
4 };
Slika 4.26 Dodavanje stilova u kôdu
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4 x:Class="WorkingWithStyles.StyleXAML">
5 <ContentPage.Resources>
6 <ResourceDictionary>
7 <Style x:Key="ButtonStyle" TargetType="Button">
8 <Setter Property="BackgroundColor" Value="Yellow"/>
9 <Setter Property="BorderRadius" Value="0"/>
10 <Setter Property="HeightRequest" Value="42"/>
11 </Style>
12 </ResourceDictionary>
13 </ContentPage.Resources>
14 <Button Text="Style Me XAML" Style="{StaticResource ButtonStyle}"
/>
15 </ContentPage>
Slika 4.27 Dodavanje stilova u XAML-u
4.6. Okidači
Kada se govori o akcijama koje slijede kao rezultat neke korisničke intervencije tada se
uglavnom govori o okidačima (eng. triggers). Okidači mogu biti postavljeni tako da
promjene izgled kontrole ili pozovu neku metodu u zavisnosti od toga šta je potrebno da se
izvrši. U XAML-u se deklarativno mogu postaviti okidači da reaguju na određene događaje.
Postoje sljedeća četiri okidača [26]:
1) Property okidač – okidač je aktiviran kada se neka kontrola postavi na predefinisanu
vrijednost. Primjer property okidača kada se fokus prenese na polje za unos imena
pri čemu se mijenja boja polja u plavu je prikazan na slici 4.28.
1 <Entry Placeholder="Ime">
2 <Entry.Triggers>
3 <Trigger TargetType="Entry"
4 Property="IsFocused" Value="True">
5 <Setter Property="BackgroundColor" Value="Blue" />
6 </Trigger>
7 </Entry.Triggers>
8 </Entry>
Slika 4.28 Property okidač u XAML-u
27
2) Data okidač – koristi povezivanje podataka (data binding) kako bi se pokrenula
akcija na osnovu promjene vrijednosti neke druge kontrole. Primjer data okidača je
dat u nastavku: Ukoliko je tekstualno polje (x:Name="entry") prazno vrši se
okidanje i onesposobljava se odgovarajuće dugme za unos podataka. Ukoliko
tekstualno polje nije prazno dugme postaje upotrebljivo. Primjer je prikazan na slici
4.29.
1 <Entry x:Name="entry"
2 Text=""
3 Placeholder="required field" />
4
5 <Button x:Name="button" Text="Save"
6 FontSize="Large"
7 HorizontalOptions="Center">
8 <Button.Triggers>
9 <DataTrigger TargetType="Button"
10 Binding="{Binding Source={x:Reference entry},
11 Path=Text.Length}"
12 Value="0">
13 <Setter Property="IsEnabled" Value="False" />
14 </DataTrigger>
15 </Button.Triggers>
16 </Button>
Slika 4.29 Data okidač u XAML-u
3) Event okidač – okidač se aktivira kada dođe do nekog “događaja” na kontroli kao
što je prikazano na slici 4.30.
1 <EventTrigger Event="Clicked">
2 <local:NumericValidationTriggerAction />
3 </EventTrigger>
Slika 4.30 Event okidač u XAML-u
4) Multi okidač – dozvoljava da se postave višestruki uslovi za okidač kao što je
prikazano na slici 4.31.
1 <MultiTrigger TargetType="Button">
2 <MultiTrigger.Conditions>
3 <BindingCondition Binding="{Binding Source={x:Reference email},
4 Path=Text.Length}" Value="0" />
5 <BindingCondition Binding="{Binding Source={x:Reference phone},
6 Path=Text.Length}" Value="0" />
7 </MultiTrigger.Conditions>
8 <Setter Property="IsEnabled" Value="False" />
Slika 4.31 Multi okidač u XAML-u
4.7. Geste
Xamarin.Forms omogućava i upotrebu određenih gesti (eng. Gestures) tj. pokreta na ekranu
uređaja koje mogu rezultirati određenim akcijama. Ovo se postiže kroz upotrebu ugrađene
GestureRecognizer klase. Dva tipa gesti koje ova klasa podržava su Tapšanje (Tap) i
Stezanje (Pinch).
28
4.7.1. Tapšanje
XAML i C# primjeri upotrebe Tapšanja za pokretanje neke akcije su dati u poglavlju 4.3.3.
Događaji i rukovaoci događajima. Ovdje je potrebno samo još dodati da je moguće odrediti
i broj tapšanja na koje će sistem reagovati. Po defaultu to je jedno tapšanje ali se može
postaviti da bude dva ili više kako je prikjazano na slikama 4.32 i 4.33:
1 <Image Grid.Row="2" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Time1.png" x:Name="Time_img" >
2 <Image.GestureRecognizers>
3 <TapGestureRecognizer
4 Tapped="LoadTime"
5 NumberOfTapsRequired="2"/>
6 </Image.GestureRecognizers>
7 </Image>
Slika 4.32 Događaj Tap u XAML-u
1 tapGestureRecognizer.NumberOfTapsRequired = 2;
Slika 4.33 Događaj Tap u kôdu
4.7.2. Stezanje
Stezanje predstavlja nešto malo kompleksniju upotrebu geste za približavanje i udaljavanje
(zoom in & out) nekog objekta. Da bi se neki element uopšte mogao zoomirati mora se prvo
kreirati instanca PinchGestureRecognizer klase, dodijeliti metoda PinchUpdated događaju
kao i dodati novi “gesture recognizer” u GestureRecognizers kolekciju. Na slikama 4.34,
4.35 i 4.36 su prikazani primjeri pomenutih akcija [27].
1 var pinchGesture = new PinchGestureRecognizer();
2 pinchGesture.PinchUpdated += (s, e) => {
3 // Handle the pinch
4 };
5 image.GestureRecognizers.Add(pinchGesture);
Slika 4.34 Kreiranje instance PinchGestureRecognizer klase u kôdu
1 <Image Source="waterfront.jpg">
2 <Image.GestureRecognizers>
3 <PinchGestureRecognizer PinchUpdated="OnPinchUpdated" />
4 </Image.GestureRecognizers>
5 </Image>
Slika 4.35 Kreiranje instance PinchGestureRecognizer klase u XAML-u
1 void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
2 {
3 // metoda
4 }
Slika 4.36 Kreiranje metode za rukovanje događajem
Ovaj se primjer odnosi na zoomiranje slike.
Zoomiranje se isto tako može primjeniti i na svaku drugi element iz korisničkog sučelja. U
tom se slučaju preporučuje da se kreira PinchToZoom kontejner i omota oko elementa koji
treba zoomirati. PinchToZoom kontejner bi ustvari trebalo da bude zasebna nova “public”
klasa koja nasljeđuje ContentView klasu. Opšti primjer sa slikom kao elementom koji se
zumira je prikazan na slikama 4.37 i 4.38 [27].
29
1 public class PinchToZoomContainer : ContentView
2 {
3 ...
4
5 public PinchToZoomContainer ()
6 {
7 var pinchGesture = new PinchGestureRecognizer ();
8 pinchGesture.PinchUpdated += OnPinchUpdated;
9 GestureRecognizers.Add (pinchGesture);
10 }
11
12 void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
13 {
14 ...
15 }
16}
Slika 4.37 Kreiranje klase i metoda za rukovanje događajem
1 public class HomePageCS : ContentPage
2 {
3 public HomePageCS ()
4 {
5 Content = new Grid {
6 Padding = new Thickness (20),
7 Children = {
8 new PinchToZoomContainer {
9 Content = new Image { Source = ImageSource.FromFile
"waterfront.jpg") }
10 }
11 }};}}
Slika 4.38 “Omotavanje“ kôda oko elementa
30
koji je popunjen metodama, klasama i event handler koji služe za prikaz i izmjenu podataka
[29].
Pojednostavljeno rečeno, MVVM je arhitektura koja omogućava odvojen prikaz korisničkog
sučelja (View), obradu sve programske logike u pozadini (ViewModel) i pohranu podataka
(Model). Ova je arhitektura jako podobna jer omogućava razdvajanje grafike, kôda i
podataka sa ciljem jednostavnijeg, preglednijeg i lakšeg razvoja aplikacije, otklanjanja
grašaka i boljeg pregleda. Posebna prednost je kada se radi sa podacima smještenim u bazi
podataka. Xamarin ima ugrađenu podršku i za SQLite.
Open-source Da Da Ne
Podrška za DOM Da Ne Da
Performanse na nivou Ne Da Da
nativnih
31
Sa druge strane Xamarin je bolje rješenje kada se radi o velikim i komplikovanim aplikacija
jer je Visual C# jedan od najmoćnijih programski jezika, a pored toga je moguće iskoristiti
i postojeće iOS i Android biblioteke kako bi se ostvarilo što bolje prevođenje u nativni kôd.
Appcelerator Titanium se nalazi između ova dva rješenje jer primjenjuje sličan sistem
prevođenje u nativni kôd kao i Xamarian, ali ipak ne koristi svu snagu i mogućnosti
programskoj jezika C# i platformskih biblioteka kao što to radi Xamarin.
Zaključaj je da odabir razvojnog okruženja je stvar namjene i preferencija samog korisnika.
Međutim, iako su PhoneGap i Appcelerator dosta popularnija rješenja najprije zbog cijene i
upotrebe vrlo popularnih web programskih jezika, Xamarin je možda bolje rješenje jer kod
izrade malih aplikacija može uraditi isto što i pomenuta dva alata, dok kod izrade zahtjevnijih
aplikacija može uraditi mnogo više zahvaljujući mogućnostima C# jezika.
32
5. Razvoj mobilne aplikacije “Converter”
upotrebom Xamarin cross-platform razvojnog
okruženja.
Osnovna ideja cross-platform programskog rješenja je da se omogući razvoj osnovnog kôda
i korisničkog sučelja za više platformi, upotrebom jednog od popularnih razvojnih
programskih jezika, gdje bi se oni dijelovi kôda koji su specifični za svaku platformu
razvijali odvojeno upotrebom sučelja (eng. Interfaces) unutar projekta za tu određenu
platformu.
Mobilna plikacija “Converter”, koja je izrađena upotrebom Xamarin razvojnog okruženja
kao praktični dio ovog završnog rada je zamišljena i realizovana da bude konverter najčešće
korištenih mjernih jedinica. Izabrano je dvet mjernih jedinica: Distance (dužina), Area
(Povšina), Temperature (Temperatura), Weight (Težina/Masa), Volume (Zapremina),
Speed(Brzina), Pressure (Pritisak), Power(Snaga) i Time (Vrijeme). Aplikacija je
realizovana upotrebom engleskog jezika i mjernih jedinica sa skraćenicama prema
međunarodnom sistemu.
Korisničko sučelje i poslovna logika (code-behind) su razdvojeni na način da je korisničko
sučelje izvedeno i stilirano upotrebom XAML elemenata dok je svo procesiranje podataka
izvedeno upotrebom klasa i metoda pisanih u Visual C# kôdu.
Kompletan kôd (Visual C# i XAML) je urađen sa namjerom da bude 100% upotrebljiv na
svim platformama kako bi se pokazala učinkovitos cross-platform pristupa razvoju mobilnih
aplikacija.
33
se mora posebno preuzeti sa Microsoft web lokacije. Minimalni uslov za Windows SDK je
verzija 8.
Pored pomenutih alata koji uključuju i emulatore mobilnih uređaja, moguće je preuzeti i
posebne pakete sa dodatnim emulatorima za Android i Windows Phone uređaje. Ovo je
posebno važno kod Android uređaja jer emulatori koji dolaze u sklopu Android SDK su jako
spori i prilično neugodni za upotrebu. Xamarin nudi opciju preuzimanja Xamarin Android
Playera, skupa emulatora koje je dizajnirao Xamarin a koji su mnogo brži i pogodniji za
upotrebu.
Xamarin takođe omogućava i integraciju u Microsoft Visual Studio 2012, 2013 i 2015.
Dostupne Xamarin verzije:
34
5.1.1. Hardverski i softverski zahtjevi za instalaciju
Hardverski i softverski zahtjevi za instalaciju svih neophodnih komponenti se razlikuju za
svaku pojedinačnu platformu:
Android – ova platforma nema nekih posebnih hardverskih zahtjeva izuzev da sistem
podržava softversku virtualizaciju jer se za pokretanje Android emulatora koristi
VirtualBox alat za virtualizaciju. Pored ovog zahtjeva nema drugih posebnih zahtjeva
35
5.3. Struktura mobilne aplikacije „Converter“
Mobilna aplikacija “Converter“ je zamišljena na način da se pri pokretanju aplikacije vrši
direktno učitavanje glavne tj. početne stranice (Main) te se na ekranu uređaja postavlja
Main.xaml. Pokretanje aplikacije se po default-u vrši iz klase App.cs koja je automatski
kreirana i izvedena iz bazne klase Application kao što je prikazano na slici 5.2.
1 public class App : Application
2 {
3 public App()
4 {
5 // The root page of your application
6 MainPage = new NavigationPage(new Main());
7 } }
Slika 5.2 Primjer klase App.cs
Unutar konstruktora za App.cs se nalazi instrukcija za kreiranje nove instance početne
(Main) stranice aplikacije. Početna stranica se sastoji od pomenutog XAML dokumenta i
prateće XAML.cs klase tj. code-behind klase. U Main.xaml su smješteni svi elementi koji
definišu izgled i funkcionalnost ove stranice. Na slikama 5.2 i 5.3 je prikazano korisničko
sučelje mobilne aplikacije “Converter“ na Android i Windows Phone emulatoru kao i
odgovaraju'i XAML kôd.
37
64 Tapped="LoadWeight"/>
65 </Image.GestureRecognizers>
66 </Image>
67 <Image Grid.Row="1" Grid.Column="1" Style="{StaticResource
ButtonStyle}" Source="Volume1.png">
68 <Image.GestureRecognizers>
69 <TapGestureRecognizer
70 Tapped="LoadVolume"/>
71 </Image.GestureRecognizers>
72 </Image>
73 <Image Grid.Row="1" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Speed1.png">
74 <Image.GestureRecognizers>
75 <TapGestureRecognizer
76 Tapped="LoadSpeed"/>
77 </Image.GestureRecognizers>
78 </Image>
79 <Image Grid.Row="2" Grid.Column="0" Style="{StaticResource
ButtonStyle}" Source="Pressure1.png">
80 <Image.GestureRecognizers>
81 <TapGestureRecognizer
82 Tapped="LoadPressure"/>
83 </Image.GestureRecognizers>
84 </Image>
85 <Image Grid.Row="2" Grid.Column="1" Style="{StaticResource
ButtonStyle}" Source="Power1.png">
86 <Image.GestureRecognizers>
87 <TapGestureRecognizer
88 Tapped="LoadPower"/>
89 </Image.GestureRecognizers>
90 </Image>
91 <Image Grid.Row="2" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Time1.png">
92 <Image.GestureRecognizers>
93 <TapGestureRecognizer
94 Tapped="LoadTime"/>
95 </Image.GestureRecognizers>
96 </Image>
97 </Grid>
98</Grid>
99</ContentPage>
Slika 5.4 XAML kôd za korisničko sučelje mobilne aplikacije “Converter“
Navigacija se dalje odvija na način da se kao odgovor na “Tap“ gestu na neku od slika ili
dugme “Settings“ pokreće odgovarajuća akcija. Struktura aplikacije je data na slici 5.3.
38
Slika 5.5 Struktura mobilne aplikacije “Converter“
Sve navedene stranice (od Distance do Time) su izrađene i uređene upotrebom XAML kôda
sa Visual C# kôdom u pratećim dokumentima.
“Tap“ gesta na bilo koju od slika vodi na sljedeću stranicu (ili jednu od ostalih koje imaju
identičan izgled izuzev naslovne labele) čiji izgled je prikazan na slici 5.4.
39
Visual C# code-behind za svaku od stranica je zadužen da procesira odgovarajuće ulazne
podatke pri svakom definisanom događaju. Događaji na koje su postavljeni handler-i su
prikazani na slikama 5.7, 5.8 i 5.9.
1 CE.Clicked += (sender, e) =>
2 {
3 if (Input_value.Text.Length > 0)
4 {
5 Input_value.Text = Input_value.Text.Substring(0,
(Input_value.Text.Length - 1));
6 Conversion();
7 }};
Slika 5.7 Pritisak na bilo koje dugme
1 Input_units.SelectedIndexChanged += (sender, e) =>
2 {
3 Conversion();
4 };
5
6 Output_units.SelectedIndexChanged += (sender, e) =>
7 {
8 Conversion();
9 };
Slika 5.8 Promjena pri odabiru druge mjerne jedinice
1 poz_neg.Clicked += (sender, e) =>
2 {
3 DisplayAlert("Alert!", "Area cannot be negative", "OK");
4 return;
5 };
Slika 5.9 Reakcija pri pokušaju promjene predznaka mjerne jedinice
Dakle proces je postavljen tako da se automatski vrši konverzija mjernih jedinica pri svakoj
promjeni vrijednosti konvertovane jedinice kao i pri svakoj promjeni odabranih mjernih
jedinica. Promjena vrijednosti konvertovane jedinice se dešava, dakle, samo nakon pritiska
na neko od dugmadi na tastaturi. Takođe je u svakom od konvertora podešena i reakcija na
pokušaj promjene predznaka konvertovane jedinice, npr. dužina ili površina ne mogu biti
negativni i u tom se slučaju pojavljuje odgovarajuća poruka na ekranu uređaja, dok
temperatura (C i F) mogu.
Što se tiče dugmeta “Settings“, pritiskom na to dugme otvara se jednostavan meni sa tri
opcije: About, Contact i Cancel. Sam meni je realizovan kao “asycn void PopUp” metoda
na način da se kreira nova instanca DisplayActionSheeta koja sadrži naslov i tri opcije. Za
razliku od kreiranja nove instance nekog drugog objekta gdje bi se koristila ključna riječ
“new“, ovdje se koristi ključna riječ “await“ što u isto vrijeme kreira novu instancu ali i
zadržava otvoreni prozor na ekranu u isčekivanju korisničke akcije tj. pritiska na jednu od
tri ponuđene opcije.
Ključna riječ “async“ je dio verzije 5 Visual C# programskog jezika i omogućava da se
pokrenuta async metoda izvršava kao odvojena nit (thread) uporedo sa drugim dijelom
programa a rezultati se lako prikazuju kada je metoda gotova. Razlog upotrebe ove ključne
riječi je postojanje await opcije kreiranja nove instance DisplayActionSheet. U slučaju da
PoPUp metoda nije deklarisana kao async, došlo bi do blokade kompletnog programa kao
rezultat izvršavanja await metode u kojoj se čeka na akciju korisnika. Kada god se unutar
40
neke metode pojavi await ključna riječ ta se metoda mora deklarisati kao Async upravo iz
razloga što postoji neka vrsta čekanja (bilo na korisnika ili neki drugi proces) koja može
dovesti do zaustavljanja izvršavanja programa i njegove blokade. Primjer je prikazan na slici
5.10.
1 async void PopUp(object sender, EventArgs args)
2 {
3 var action = await DisplayActionSheet("Settings", "Cancel",
null, "About", "Contact");
4 if (action.Equals("About"))
5 {
6 await DisplayAlert("About", "Converter\nVersion 1.0
\n\nCopyright © 2015 by Faruk Salkić
\n\nUnlimited distribution and use of this program is permitted.
\n\nAny modification of this program or code within without prior
approval by the author is strictly prohibited.
\n", "OK");
7
8 }
9 else if (action.Equals("Contact"))
10 {
11 await DisplayAlert("Contact",
"faruk.salkic@empirica.edu.ba
\nfaruk.salkic@gmail.com", "OK");
12 }
13 }
Slika 5.10 Primjer async metode
Izlazak iz konvertera ka početnoj stranici se vrši pomoću dugmeta Exit ili pritiskom na
sistemsku tipku Back što ima isti rezultat a to je zaustavljanje i zatvaranje trenutnog procesa.
Drugim riječima ne postoji mogućnost otvaranja više stranica konvertera uporedo i držanje
istih u stacku čime se štede resursi uređaja (prvenstveno memorija).
Pri svakom tapšanju na bilo koju sliku na početnoj stranici iznova se pokreće odgovarajući
konverter.
Naredba za izlaz i zatvaranje same aplikacije nije ugrađena jer iOS ne podržava eksplicitno
zatvaranje aplikacija te bi ista bila primjenjiva samo na Android i Windows Phone.
41
Zaključak
U uvodu ovog rada naglašena je važnost mobilnih uređaja kao i to da se sve više internet i
web saobraćaja obavlja preko pomenutih. Ovo je direktan rezultat velikog napretka u razvoju
mobilnih uređaja, povećanju njihovih kapaciteta i funkcionalnisti kao i unaprijeđenju i
pojednostavljenju njihovog korisničkog sučelja. U ovom momentu postoji više različitih
operativnih sistema na kojima ovi uređaji rade ali je, statistički gledano, tržište dominirano
od strane tri najpopularnije platforme: Android, iOS i Windows Phone. Svaka od platformi
je specifična i za svaku od njih postoji drugačiji način razvoja aplikacija.
Nativni razvoj aplikacija, koristeći odgovarajuće programske jezike kao i razvojna
okruženja, iziskuje da programer detaljno poznaje svaki od pomenutih jezika i okruženja
kako bi bio u mogućnosti razviti aplikaciju za svaku od platformi. Pored toga tu je i vrijeme
koje je potrebno sekvencijalno uložiti u razvoj istih. Cross-platform pristup razvoju
aplikacija nudi djelomično ili kompletno rješenje ovog problema, u ovisnosti od namjene i
komplikovanosti željene aplikacije.
Cilj ovog ovog rada je analiza Xamarin razvojnog okruženja, a posebice Xamarin.Forms
koji omogućava programeru specijalizovanom za C# programski jezik i .NET tehnologije
da učinkovito iskoristi svu snagu i mogućnosti pomenutih. Xamarin.Forms omogućava da
se, koristeći XAML, relativno jednostavno kreiraju aplikacije čije grafičko sučelje nije
previše komplikovano. Nedostatak ovog pristupa upotrebom Xamarin.Forms je nepostojanje
grafičkog dizajnera koji bi programeru omogućio jednostavan i brz uvid (vizualizaciju)
onoga na čemu radi, tako da se programer mora oslanjati na sopstvenu kreativnost, detaljno
i precizno uređivanje elemenata grafičkog sučelja i čestu kompilaciju i emulaciju kako bi
osigurao da su svi elementi na svom mjestu i da je sučelje funkcionalno.
Xamarin.Android i Xamarin.iOS s drugu stranu omogućavaju razvoj nativnih aplikacija
upotrebom C# programskog jezika i .NET tehnologija kao i vrlo preglednog grafičkog
dizajnera što umnogome olakšava kreiranje čak i komplikovanih grafičkih sučelja.
Nedostatak je taj što se za svaku platformu kôd mora nanovo pisati dok je prednost što se to
sve može uraditi upotrebom C# programskog jezika te uz prenos i upotrebu velikog dijela
istog kôda.
42
Bibliografija
[1] “http://www.statista.com/statistics/412108/global-smartphone-shipments-global-
region/,” 2015. [Na mreži].
[4] “http://www.statista.com/statistics/263795/number-of-available-apps-in-the-apple-
app-store/,” [Na mreži].
[5] “http://searchsoftwarequality.techtarget.com/definition/native-application-native-
app,” [Na mreži].
[13] “https://developer.xamarin.com/guides/cross-
platform/application_fundamentals/building_cross_platform_applications/part_1_-
_understanding_the_xamarin_mobile_platform/,” [Na mreži].
[14] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/getting-
started/introduction-to-xamarin-forms/,” [Na mreži].
[17] C. Petzold, “How does Xamarin.Forms fit in?,” u Creating Mobile Apps with
Xamarin.Forms Book Preview 2, Microsoft Press, 2015, p. 8.
43
[18] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/user-
interface/xaml-basics/getting_started_with_xaml/,” [Na mreži].
[19] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/user-
interface/xaml-basics/,” [Na mreži].
[20] C. Petzold, “Data Binding,” u Creating Mobile Apps with Xamarin.Forms Preview 2,
Microsoft Press, 2015, p. 402.
[21] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/user-
interface/xaml-basics/data_binding_basics/,” [Na mreži].
[25] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-
with/styles/,” [Na mreži].
[26] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-
with/triggers/,” [Na mreži].
[27] “https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-
with/gestures/#Adding_a_Pinch_Gesture_Recognizer,” [Na mreži].
[30] “http://www.cygnet-infotech.com/blog/phonegap-or-titanium-or-xamarin-which-
cross-platform-should-you-choose,” [Na mreži].
44
Dodatak
U nastavku se nalazi dio izvornog kôda mobilne aplikacije “Converter” koji se odnosi na
osnovnu klasu App.cs, te forme i prateće klase Main.xaml, Main.xaml.ca, Distance.xaml i
Distance.xaml.cs. Ostatak kôda se nalazi na pratećem DVD disku s obzirom na dužinu.
App.cs:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 using Xamarin.Forms;
7
8 namespace Converter_X
9 {
10 public class App : Application
11 {
12 public App()
13 {
14 // The root page of your application
15 MainPage = new NavigationPage(new Main());
16 }
17 }
18}
Main.xaml:
1 <?xml version="1.0" encoding="utf-8" ?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4 x:Class="Converter_X.Main">
5 <ContentPage.Resources>
6 <ResourceDictionary>
7 <Style x:Key="ButtonStyle" TargetType="Button">
8 <Setter Property="BackgroundColor" Value="Green"/>
9 </Style>
10 </ResourceDictionary>
11 </ContentPage.Resources>
12 <Grid>
13 <Grid.RowDefinitions>
14 <RowDefinition Height="50" />
15 <RowDefinition Height="*" />
16 </Grid.RowDefinitions>
17 <Grid.ColumnDefinitions>
18 <ColumnDefinition Width="*" />
19 </Grid.ColumnDefinitions>
20 <Grid Grid.Row="0">
21 <Image HorizontalOptions="Start" Source="Settings.png">
22 <Image.GestureRecognizers>
23 <TapGestureRecognizer
24 Tapped="PopUp"/>
25 </Image.GestureRecognizers>
26 </Image>
45
27 <Label Text="CONVERTER" HorizontalOptions="Center" FontSize="30"
FontAttributes="Bold"></Label>
28 </Grid>
29 <Grid Grid.Row="1">
30 <Grid.RowDefinitions>
31 <RowDefinition Height="*" />
32 <RowDefinition Height="*" />
33 <RowDefinition Height="*" />
34 </Grid.RowDefinitions>
35 <Grid.ColumnDefinitions>
36 <ColumnDefinition Width="*" />
37 <ColumnDefinition Width="*" />
38 <ColumnDefinition Width="*" />
39 </Grid.ColumnDefinitions>
40 <Image Grid.Row="0" Grid.Column="0" Style="{StaticResource
ButtonStyle}" Source="Distance1.png">
41 <Image.GestureRecognizers>
42 <TapGestureRecognizer
43 Tapped="LoadDistance"/>
44 </Image.GestureRecognizers>
45 </Image>
46 <Image Grid.Row="0" Grid.Column="1" Style="{StaticResource
ButtonStyle}" Source="Area1.png">
47 <Image.GestureRecognizers>
48 <TapGestureRecognizer
49 Tapped="LoadArea"/>
50 </Image.GestureRecognizers>
51 </Image>
52 <Image Grid.Row="0" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Temperature1.png">
53 <Image.GestureRecognizers>
54 <TapGestureRecognizer
55 Tapped="LoadTemperature"/>
56 </Image.GestureRecognizers>
57 </Image>
58 <Image Grid.Row="1" Grid.Column="0" Style="{StaticResource
ButtonStyle}" Source="Weight1.png">
59 <Image.GestureRecognizers>
60 <TapGestureRecognizer
61 Tapped="LoadWeight"/>
62 </Image.GestureRecognizers>
63 </Image>
64 <Image Grid.Row="1" Grid.Column="1" Style="{StaticResource
ButtonStyle}" Source="Volume1.png">
65 <Image.GestureRecognizers>
66 <TapGestureRecognizer
67 Tapped="LoadVolume"/>
68 </Image.GestureRecognizers>
69 </Image>
70 <Image Grid.Row="1" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Speed1.png">
71 <Image.GestureRecognizers>
72 <TapGestureRecognizer
73 Tapped="LoadSpeed"/>
74 </Image.GestureRecognizers>
75 </Image>
76 <Image Grid.Row="2" Grid.Column="0" Style="{StaticResource
ButtonStyle}" Source="Pressure1.png">
77 <Image.GestureRecognizers>
46
78 <TapGestureRecognizer
79 Tapped="LoadPressure"/>
80 </Image.GestureRecognizers>
81 </Image>
82 <Image Grid.Row="2" Grid.Column="1" Style="{StaticResource
ButtonStyle}" Source="Power1.png">
83 <Image.GestureRecognizers>
84 <TapGestureRecognizer
85 Tapped="LoadPower"/>
86 </Image.GestureRecognizers>
87 </Image>
88 <Image Grid.Row="2" Grid.Column="2" Style="{StaticResource
ButtonStyle}" Source="Time1.png">
89 <Image.GestureRecognizers>
90 <TapGestureRecognizer
91 Tapped="LoadTime"/>
92 </Image.GestureRecognizers>
93 </Image>
94 </Grid>
95</Grid>
96</ContentPage>
Main.xaml.cs:
1 using System;
2 using Xamarin.Forms;
3
4 namespace Converter_X
5 {
6 public partial class Main : ContentPage
7 {
8 public Main()
9 {
10 InitializeComponent();
11 NavigationPage.SetHasNavigationBar(this, false);
12 }
13
14 //Methods (9 methods) invoked when image buttons on the main
page are tapped
15 void LoadDistance(object sender, EventArgs args)
16 {
17 Navigation.PushAsync(new Distance());
18 }
19
20 void LoadArea (object sender, EventArgs args)
21 {
22 Navigation.PushAsync(new Area());
23 }
24
25 void LoadTemperature (object sender, EventArgs args)
26 {
27 Navigation.PushAsync(new Temperature());
28 }
29
30 void LoadWeight (object sender, EventArgs args)
31 {
32 Navigation.PushAsync(new Weight());
33 }
47
34
35 void LoadVolume (object sender, EventArgs args)
36 {
37 Navigation.PushAsync(new Volume());
38 }
39
40 void LoadSpeed(object sender, EventArgs args)
41 {
42 Navigation.PushAsync(new Speed());
43 }
44
45 void LoadPressure (object sender, EventArgs args)
46 {
47 Navigation.PushAsync(new Pressure());
48 }
49
50 void LoadPower (object sender, EventArgs args)
51 {
52 Navigation.PushAsync(new Power());
53 }
54
55 void LoadTime (object sender, EventArgs args)
56 {
57 Navigation.PushAsync(new Time());
58 }
59
60 //Method for calling settings popup
61 async void PopUp (object sender, EventArgs args)
62 {
63 var action = await DisplayActionSheet("Settings", "Cancel",
null, "About", "Contact");
64 if (action.Equals("About"))
65 {
66 await DisplayAlert("About", "Converter\nVersion
1.0\n\nCopyright © 2015 by Faruk Salkić\n\nUnlimited distribution and use
of this program is permitted.\n\nAny modification of this program or code
within without prior approval by the author is strictly prohibited.\n",
"OK");
67
68 }
69 else if (action.Equals("Contact"))
70 {
71 await DisplayAlert("Contact",
"faruk.salkic@empirica.edu.ba\nfaruk.salkic@gmail.com", "OK");
72 }
73 }
74 }
75}
Distance.xaml:
1 <?xml version="1.0" encoding="utf-8" ?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4 x:Class="Converter_X.Distance">
5 <ContentPage.Resources>
6 <ResourceDictionary>
7 <Style x:Key="ButtonStyle" TargetType="Button">
48
8 <Setter Property="BackgroundColor" Value="#D1CFCF"/>
9 <Setter Property="BorderRadius" Value="4"/>
10 <Setter Property="FontSize" Value="25"/>
11 </Style>
12 <Style x:Key="LabelStyle" TargetType="Label">
13 <Setter Property="BackgroundColor" Value="#D1CFCF"/>
14 <Setter Property="FontAttributes" Value="Bold"/>
15 <Setter Property="XAlign" Value="Center"/>
16 <Setter Property="YAlign" Value="Center"/>
17 <Setter Property="FontSize" Value="30"/>
18 </Style>
19 <Style x:Key="PickerStyle" TargetType="Picker">
20 <Setter Property="BackgroundColor" Value="Transparent"/>
21 <Setter Property="VerticalOptions" Value="Center"/>
22 </Style>
23 </ResourceDictionary>
24 </ContentPage.Resources>
25<Grid>
26 <Grid.RowDefinitions>
27 <RowDefinition Height=".6*" />
28 <RowDefinition Height="2.8*" />
29 <RowDefinition Height="6.6*" />
30 </Grid.RowDefinitions>
31 <Grid.ColumnDefinitions>
32 <ColumnDefinition Width="*" />
33 </Grid.ColumnDefinitions>
34 <Grid Grid.Row="0">
35 <Image HorizontalOptions="Start" Source="Settings.png">
36 <Image.GestureRecognizers>
37 <TapGestureRecognizer
38 Tapped="PopUp"/>
39 </Image.GestureRecognizers>
40 </Image>
41 <Label Text="DISTANCE" HorizontalOptions="Center" FontSize="30"
FontAttributes="Bold"></Label>
42 </Grid>
43 <Grid Grid.Row="1" BackgroundColor="Transparent">
44 <Grid.RowDefinitions>
45 <RowDefinition Height="*" />
46 <RowDefinition Height="*" />
47 </Grid.RowDefinitions>
48 <Grid.ColumnDefinitions>
49 <ColumnDefinition Width="6.5*" />
50 <ColumnDefinition Width="3.5*" />
51 </Grid.ColumnDefinitions>
52 <Picker Grid.Row="0" Grid.Column="1" x:Name="Input_units"
Style="{StaticResource PickerStyle}" Title="Select:" ></Picker>
53 <Picker Grid.Row="1" Grid.Column="1" x:Name="Output_units"
Style="{StaticResource PickerStyle}" Title="Select:"></Picker>
54 <Label Grid.Row="0" Grid.Column="0" x:Name="Input_value"
Style="{StaticResource LabelStyle}" ></Label >
55 <Label Grid.Row="1" Grid.Column="0" x:Name="Output_value"
Style="{StaticResource LabelStyle}"></Label >
56 </Grid>
57 <Grid Grid.Row="2">
58 <Grid.RowDefinitions>
59 <RowDefinition Height="*" />
60 <RowDefinition Height="*" />
61 <RowDefinition Height="*" />
49
62 <RowDefinition Height="*" />
63 <RowDefinition Height="30" />
64 </Grid.RowDefinitions>
65 <Grid.ColumnDefinitions>
66 <ColumnDefinition Width="*" />
67 <ColumnDefinition Width="*" />
68 <ColumnDefinition Width="*" />
69 <ColumnDefinition Width="*" />
70 </Grid.ColumnDefinitions>
71 <Button Grid.Row="0" Grid.Column="0" x:Name="No_7" Text="7"
Style="{StaticResource ButtonStyle}"></Button>
72 <Button Grid.Row="0" Grid.Column="1" x:Name="No_8" Text="8"
Style="{StaticResource ButtonStyle}"></Button>
73 <Button Grid.Row="0" Grid.Column="2" x:Name="No_9" Text="9"
Style="{StaticResource ButtonStyle}"></Button>
74 <Button Grid.Row="0" Grid.Column="3" x:Name="CE" Text="CE"
Style="{StaticResource ButtonStyle}"></Button>
75 <Button Grid.Row="1" Grid.Column="0" x:Name="No_4" Text="4"
Style="{StaticResource ButtonStyle}"></Button>
76 <Button Grid.Row="1" Grid.Column="1" x:Name="No_5" Text="5"
Style="{StaticResource ButtonStyle}"></Button>
77 <Button Grid.Row="1" Grid.Column="2" x:Name="No_6" Text="6"
Style="{StaticResource ButtonStyle}"></Button>
78 <Button Grid.Row="1" Grid.Column="3" x:Name="C" Text="C"
Style="{StaticResource ButtonStyle}"></Button>
79 <Button Grid.Row="2" Grid.Column="0" x:Name="No_1" Text="1"
Style="{StaticResource ButtonStyle}"></Button>
80 <Button Grid.Row="2" Grid.Column="1" x:Name="No_2" Text="2"
Style="{StaticResource ButtonStyle}"></Button>
81 <Button Grid.Row="2" Grid.Column="2" x:Name="No_3" Text="3"
Style="{StaticResource ButtonStyle}"></Button>
82 <Button Grid.Row="2" Grid.Column="3" x:Name="poz_neg" Text="+/-"
Style="{StaticResource ButtonStyle}"></Button>
83 <Button Grid.Row="3" Grid.ColumnSpan="2" x:Name="No_0" Text="0"
Style="{StaticResource ButtonStyle}"></Button>
84 <Button Grid.Row="3" Grid.Column="2" x:Name="dot" Text="."
Style="{StaticResource ButtonStyle}"></Button>
85 <Button Grid.Row="3" Grid.Column="3" x:Name="Done" Text="Exit"
Style="{StaticResource ButtonStyle}"></Button>
86 <Label Grid.Row="4" Grid.ColumnSpan="4" Text="©Faruk Salkić,
2015." TextColor="Gray"></Label>
87 </Grid>
88 </Grid>
89</ContentPage>
Distance.xaml.cs:
1 using System;
2 using System.Collections.Generic;
3
4 using Xamarin.Forms;
5
6 namespace Converter_X
7 {
8 public partial class Distance : ContentPage
9 {
10 public Distance()
11 {
50
12 InitializeComponent();
13 NavigationPage.SetHasNavigationBar(this, false);
14
15 //List of measuring units is added to the pickers (view
controls similar to dropdown menus)
16 foreach (string item in DistanceList)
17 {
18 Input_units.Items.Add(item);
19 Output_units.Items.Add(item);
20 }
21
22 //Button click events: numbers are added and Conversion
method is invoked each time there is a click on keypad
23 No_0.Clicked += (sender, e) => {
24 if (Input_value.Text != "")
25 { Input_value.Text += "0"; Conversion(); }
26 else return;};
27 No_1.Clicked += (sender, e) => { Input_value.Text += "1";
Conversion(); };
28 No_2.Clicked += (sender, e) => { Input_value.Text += "2";
Conversion(); };
29 No_3.Clicked += (sender, e) => { Input_value.Text += "3";
Conversion(); };
30 No_4.Clicked += (sender, e) => { Input_value.Text += "4";
Conversion(); };
31 No_5.Clicked += (sender, e) => { Input_value.Text += "5";
Conversion(); };
32 No_6.Clicked += (sender, e) => { Input_value.Text += "6";
Conversion(); };
33 No_7.Clicked += (sender, e) => { Input_value.Text += "7";
Conversion(); };
34 No_8.Clicked += (sender, e) => { Input_value.Text += "8";
Conversion(); };
35 No_9.Clicked += (sender, e) => { Input_value.Text += "9";
Conversion(); };
36 C.Clicked += (sender, e) => { Input_value.Text = "";
Conversion(); };
37 CE.Clicked += (sender, e) =>
38 {
39 if (Input_value.Text.Length > 0)
40 {
41 Input_value.Text = Input_value.Text.Substring(0,
(Input_value.Text.Length - 1));
42 Conversion();
43 }
44 };
45 dot.Clicked += (sender, e) =>
46 {
47 if (Input_value.Text.Contains("."))
48 { return; }
49 { Input_value.Text += "."; };
50 };
51 poz_neg.Clicked += (sender, e) =>
52 {
53 DisplayAlert("Alert!", "Distance cannot be negative",
"OK");
54 return;
55 };
56 Done.Clicked += (s, e) =>
51
57 {
58 Navigation.RemovePage(this);
59 };
60
61 Input_value.Text = "";
62
63 //Conversion method is invoked every time when measuring
units are changed
64 Input_units.SelectedIndexChanged += (sender, e) =>
65 {
66 Conversion();
67 };
68
69 Output_units.SelectedIndexChanged += (sender, e) =>
70 {
71 Conversion();
72 };
73 }
74
75 //List of measurin units is created
76 List<string> DistanceList = new List<string>
77 {
78 "mm", "cm", "m", "km","inch","foot","yard","mile"
79 };
80
81 //Method for calling settings popup
82 async void PopUp(object sender, EventArgs args)
83 {
84 var action = await DisplayActionSheet("Settings",
"Cancel", null, "About", "Contact");
85 if (action.Equals("About"))
86 {
87 await DisplayAlert("About", "Converter\nVersion
1.0\n\nCopyright © 2015 by Faruk Salkić\n\nUnlimited distribution and use
of this program is permitted.\n\nAny modification of this program or code
within without prior approval by the author is strictly prohibited.\n",
"OK");
88
89 }
90 else if (action.Equals("Contact"))
91 {
92 await DisplayAlert("Contact",
"faruk.salkic@empirica.edu.ba\nfaruk.salkic@gmail.com", "OK");
93 }
94 }
95
96 //Conversion method
97 void Conversion()
98 {
99 if (Input_value.Text == "" || Input_value.Text == ".")
100 {
101 Output_value.Text = "";
102 return;
103 }
104 else if (Input_units.SelectedIndex.Equals(-1) ||
Output_units.SelectedIndex.Equals(-1))
105 {
106 return;
107 }
52
108 double input_value =
Convert.ToDouble(Input_value.Text.ToString());
109 double result;
110 string input_unit =
Input_units.Items[Input_units.SelectedIndex].ToString();
111 string output_unit =
Output_units.Items[Output_units.SelectedIndex].ToString();
112
113 switch (input_unit)
114 {
115 case "mm":
116 switch (output_unit)
117 {
118 case "mm":
119 Output_value.Text =input_value.ToString();
120 break;
121 case "cm":
122 result = input_value * 0.1;
123 Output_value.Text = result.ToString();
124 break;
125 case "m":
126 result = input_value * 0.001;
127 Output_value.Text = result.ToString();
128 break;
129 case "km":
130 result = input_value * 1e-006;
131 Output_value.Text = result.ToString("r");
132 break;
133 case "inch":
134 result = input_value * 0.03937008;
135 Output_value.Text = result.ToString();
136 break;
137 case "foot":
138 result = input_value * 0.00328084;
139 Output_value.Text = result.ToString();
140 break;
141 case "yard":
142 result = input_value * 0.001093613;
143 Output_value.Text = result.ToString();
144 break;
145 case "mile":
146 result = input_value * 6.213712e-007;
147 Output_value.Text = result.ToString();
148 break;
149 };
150 break;
151 case "cm":
152 switch (output_unit)
153 {
154 case "mm":
155 result = input_value * 10;
156 Output_value.Text = result.ToString();
157 break;
158 case "cm":
159 Output_value.Text =input_value.ToString();
160 break;
161 case "m":
162 result = input_value * 0.01;
163 Output_value.Text = result.ToString();
53
164 break;
165 case "km":
166 result = input_value * 1e-005;
167 Output_value.Text = result.ToString();
168 break;
169 case "inch":
170 result = input_value * 0.3937008;
171 Output_value.Text = result.ToString();
172 break;
173 case "foot":
174 result = input_value * 0.0328084;
175 Output_value.Text = result.ToString();
176 break;
177 case "yard":
178 result = input_value * 0.01093613;
179 Output_value.Text = result.ToString();
180 break;
181 case "mile":
182 result = input_value * 6.213712e-006;
183 Output_value.Text = result.ToString();
184 break;
185 };
186 break;
187 case "m":
188 switch (output_unit)
189 {
190 case "mm":
191 result = input_value * 1000;
192 Output_value.Text = result.ToString();
193 break;
194 case "cm":
195 result = input_value * 100;
196 Output_value.Text = result.ToString();
197 break;
198 case "m":
199 Output_value.Text =input_value.ToString();
200 break;
201 case "km":
202 result = input_value * 0.001;
203 Output_value.Text = result.ToString();
204 break;
205 case "inch":
206 result = input_value * 39.37008;
207 Output_value.Text = result.ToString();
208 break;
209 case "foot":
210 result = input_value * 3.28084;
211 Output_value.Text = result.ToString();
212 break;
213 case "yard":
214 result = input_value * 1.093613;
215 Output_value.Text = result.ToString();
216 break;
217 case "mile":
218 result = input_value * 0.0006213712;
219 Output_value.Text = result.ToString();
220 break;
221 };
222 break;
54
223 case "km":
224 switch (output_unit)
225 {
226 case "mm":
227 result = input_value * 1000000;
228 Output_value.Text = result.ToString();
229 break;
230 case "cm":
231 result = input_value * 100000;
232 Output_value.Text = result.ToString();
233 break;
234 case "m":
235 result = input_value * 1000;
236 Output_value.Text = result.ToString();
237 break;
238 case "km":
239 Output_value.Text =input_value.ToString();
240 break;
241 case "inch":
242 result = input_value * 39370.08;
243 Output_value.Text = result.ToString();
244 break;
245 case "foot":
246 result = input_value * 3280.84;
247 Output_value.Text = result.ToString();
248 break;
249 case "yard":
250 result = input_value * 1093.613;
251 Output_value.Text = result.ToString();
252 break;
253 case "mile":
254 result = input_value * 0.6213712;
255 Output_value.Text = result.ToString();
256 break;
257 };
258 break;
259 case "inch":
260 switch (output_unit)
261 {
262 case "mm":
263 result = input_value * 25.4;
264 Output_value.Text = result.ToString();
265 break;
266 case "cm":
267 result = input_value * 2.54;
268 Output_value.Text = result.ToString();
269 break;
270 case "m":
271 result = input_value * 0.0254;
272 Output_value.Text = result.ToString();
273 break;
274 case "km":
275 result = input_value * 2.54e-005;
276 Output_value.Text = result.ToString();
277 break;
278 case "inch":
279 Output_value.Text =input_value.ToString();
280 break;
281 case "foot":
55
282 result = input_value * 0.08333333;
283 Output_value.Text = result.ToString();
284 break;
285 case "yard":
286 result = input_value * 0.02777778;
287 Output_value.Text = result.ToString();
288 break;
289 case "mile":
290 result = input_value * 1.578283e-005;
291 Output_value.Text = result.ToString();
292 break;
293 };
294 break;
295 case "foot":
296 switch (output_unit)
297 {
298 case "mm":
299 result = input_value * 304.8;
300 Output_value.Text = result.ToString();
301 break;
302 case "cm":
303 result = input_value * 30.48;
304 Output_value.Text = result.ToString();
305 break;
306 case "m":
307 result = input_value * 0.3048;
308 Output_value.Text = result.ToString();
309 break;
310 case "km":
311 result = input_value * 0.0003048;
312 Output_value.Text = result.ToString();
313 break;
314 case "inch":
315 result = input_value * 12;
316 Output_value.Text = result.ToString();
317 break;
318 case "foot":
319 Output_value.Text =input_value.ToString();
320 break;
321 case "yard":
322 result = input_value * 0.3333333;
323 Output_value.Text = result.ToString();
324 break;
325 case "mile":
326 result = input_value * 0.0001893939;
327 Output_value.Text = result.ToString();
328 break;
329 };
330 break;
331 case "yard":
332 switch (output_unit)
333 {
334 case "mm":
335 result = input_value * 914.4;
336 Output_value.Text = result.ToString();
337 break;
338 case "cm":
339 result = input_value * 91.44;
340 Output_value.Text = result.ToString();
56
341 break;
342 case "m":
343 result = input_value * 0.9144;
344 Output_value.Text = result.ToString();
345 break;
346 case "km":
347 result = input_value * 0.0009144;
348 Output_value.Text = result.ToString();
349 break;
350 case "inch":
351 result = input_value * 36;
352 Output_value.Text = result.ToString();
353 break;
354 case "foot":
355 result = input_value * 3;
356 Output_value.Text = result.ToString();
357 break;
358 case "yard":
359 Output_value.Text =input_value.ToString();
360 break;
361 case "mile":
362 result = input_value * 0.0005681818;
363 Output_value.Text = result.ToString();
364 break;
365 };
366 break;
367 case "mile":
368 switch (output_unit)
369 {
370 case "mm":
371 result = input_value * 1609344;
372 Output_value.Text = result.ToString();
373 break;
374 case "cm":
375 result = input_value * 160934.4;
376 Output_value.Text = result.ToString();
377 break;
378 case "m":
379 result = input_value * 1609.344;
380 Output_value.Text = result.ToString();
381 break;
382 case "km":
383 result = input_value * 1.609344;
384 Output_value.Text = result.ToString();
385 break;
386 case "inch":
387 result = input_value * 63360;
388 Output_value.Text = result.ToString();
389 break;
390 case "foot":
391 result = input_value * 5280;
392 Output_value.Text = result.ToString();
393 break;
394 case "yard":
395 result = input_value * 1760;
396 Output_value.Text = result.ToString();
397 break;
398 case "mile":
399 Output_value.Text = input_value.ToString();
57
400 break;
401 };
402 break;
403 }
404 }
405 }
406}
58