VOLEJTE 725 517 597

Skeleton Software Facebooku Skeleton Software na Google+ Skeleton Software na Twitteru Skeleton Software na LinkedIn

Xamarin: Aplikace občanka

Blog - Xamarin

Článek ukazuje jak pomocí Xamarin Forms rychle a jednoduše vytvořit aplikaci pro Android, iOS a WP.

4. března 2017 Roman Fischer

Článek je určen vývojářům, kteří se chtějí s Xamarin Forms seznámit po praktické stránce. Pokud vás zajímá co vlastně Xamarin a Xamarin.Forms je nebo se rozhlížíte po technologii, kterou byste mohli použít k vývoji mobilních aplikací, podívejte se nejprve na náš teoretický úvod.

Pro demonstraci vytvoření jednoduché aplikace jsem si vybral aplikaci Občanka. Ta má jednu stránku, na které uživatel zadá číslo svého občanského průkazu a ona ověří, zda je toto číslo evidováno v seznamu neplatných dokladů. Samotné ověření platnosti provádí webová služba, se kterou mobilní aplikace komunikuje. Služba se nachází na adrese: http://aplikace.mvcr.cz/neplatne-doklady/doklady.aspx. Součástí aplikace je i stránka O aplikaci, kde bude uveden popis funkce a kontaktní údaje.

Založení projektu

Po spuštění Visual Studia (VS) vytvoříme nový projekt. Šablonu najdeme na záložce Cross-Platform a nazývá se Blank Xaml App (Xamarin.Forms Portable). Visual Studio vám vygeneruje několik projektů. V jednom společném (Portable) bude uložena většina vaší aplikace. Pak následují projekty pro každou platformu. Zde se nachází inicializace Xamarin.Forms. Pokud byste vytvářeli nějaké vlastní komponenty, tak jejich renderery budou uloženy v těchto projektech. Můžete se všimnout, že zde není jen projekt pro Android, iOS a Windows Phone 8.1. Naleznete zde i UWP a Windows 8.1. Vaši aplikaci vytvořenou v Xamarin.Forms půjde tedy spustit i na desktopu s Windows 8.1 nebo 10.

Xamarin(2) - Solution

Vytvoření první stránky

Ve společném projektu vytvoříme složku Pages, do které vložíme novou Forms Xaml Page s názvem MainPage.xaml. V ní si definujeme podobu naší první stránky.

        
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Skeleton.Mobile.IdentityCardValidator.Pages.MainPage">
<StackLayout>
<Label Text="Zadejte číslo OP" Style="{StaticResource Label}"/>
<Entry x:Name="IDNumber"/>
<Button Text="Odeslat" Clicked="SendButton_Click"/>
</StackLayout>
</ContentPage>

StackLayout se stará o řazení prvků pod sebe nebo vedle sebe podle nastavení vlastnosti Orientation. Entry slouží k vložení textu, v tomto případě čísla OP. Díky nastavení vlastnosti x:Name můžeme k této komponentě přistupovat v behind kódu. Button je běžné tlačítko. Vlastnost Clicked obsahuje název metody, která se postará o obsloužení toho, když uživatel na tlačítko klikne. Tuto metodu musíme v behind kódu definovat, jinak aplikaci nebude možné spustit. Label zobrazuje zadaný text. Můžete si všimnout, že této komponentě je nastavena vlastnost Style. V Xamarin.Forms si můžeme definovat vlastní styly a ty potom přiřazovat jednotlivým komponentám. Lze je definovat jen pro danou stránku ve vlastnosti ContentPage.Resources a nebo globálně v souboru App.xaml


<!--Definice stylu na stránce-->
<ContentPage.Resources>
<ResourceDictionary>

</ResourceDictionary>
</ContentPage.Resources>

<!--Definice stylu v souboru App.xaml-->
<Application.Resources>
<ResourceDictionary>
<OnPlatform x:TypeArguments="Font" WinPhone="Small" x:Key="textSize" />
<Style x:Key="Label" TargetType="Label">
<Setter Property="Font" Value="{StaticResource textSize}"/>
</Style>
</ResourceDictionary>
</Application.Resources>

OnPlatform je velmi užitečná konstrukce, která vám umožňuje nastavit na jednotlivých platformách jiné hodnoty daných vlastností. Na ukázce kódu výše je pomocí OnPlatform nastaveno, že na Windows Phone se má použít jiná velikost fontu. Na všech ostatních platformách bude použita defaultní hodnota Medium. Když se ale aplikace spustí na Windows Phone, bude použita hodnota Small. Definovat různé chování na jednotlivých platformách lze nejen v XAML, ale i v kódu například pro úpravu vlastnosti Title. Ta se totiž na Windows Phone zobrazuje trochu jinak než na ostatní platformách.


public MainPage()
{
    InitializeComponent();
    if (Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows)
    {
        this.Title = "  " + this.Title.ToLower();
    }
}

Spuštění aplikace

Nejprve musíme aplikaci říct, jakou stránku má spustit jako první. To probíhá v souboru App.xaml.cs. Nastavením vlastnosti MainPage.


public App()
{
    InitializeComponent();
    MainPage = new NavigationPage(new Pages.MainPage());
}
    

Pokud chceme v naší aplikaci zobrazovat více než jednu stránku, musíme jako MainPage nastavit buď právě NavigationPage a nebo nějakou jí podobnou (MasterDetailPage atd.) MainPage se potom stará o zobrazování našich jednotlivých ContentPage. NavigationPage se chová jako zásobník. Stránka, kterou jí předáme v konstruktoru, je brána jako hlavní a všechny následně zobrazené stránky se řadí za ní. Pokud pak uživatel mačká tlačítko zpět, jsou ze zásobníku stránky postupně vybírány a zobrazovány. Tímto způsobem se uživatel dostane zpět na hlavní stránku.

Po spuštění vidíme, že aplikace používá nejen nativní komponenty, ale na Androidu dokonce obsahuje základní prvky materiál designu. Toho je docíleno pomocí android stylu. Ten už je v šabloně připravený a jeho definici najdeme v projektu pro Android v souboru Resources\values\style.xml. Můžeme zde změnit barvy atd.

Xamarin(2) - iOSXamarin(2) - AndroidXamarin(2) - Windows Phone

private async void SendButton_Click(object sender, EventArgs e)
{
    var manager = new IDValidityManager();
    var result = await manager.CheckIDValidity(this.IDNumber.Text);
    switch (result)
    {
        case IDValidityManager.Validity.Unknown:
            await DisplayAlert("Platnost občanky", "Platnost dokladu se nepodařilo ověřit!", "OK");
            break;
        case IDValidityManager.Validity.Valid:
            await DisplayAlert("Platnost občanky", "Zadaný doklad není evidován v databázi neplatných dokladů", "OK");
            break;
        case IDValidityManager.Validity.Invalid:
            await DisplayAlert("Platnost občanky", "Zadaný doklad je evidován v databázi neplatných dokladů", "OK");
            break;
    }
}
     

Tlačítko O aplikaci

Nyní máme základní funkci aplikace realizovanou a zbývá nám už jen stránka O aplikaci. Potřebujeme další tlačítko, pomocí kterého na ní uživatel přejde. To vložíme do tzv. Toolbaru.


<ContentPage.ToolbarItems>
<ToolbarItem Name="O aplikaci" Activated="AboutApp_Click" Order="Primary" Icon="about.png"/>
</ContentPage.ToolbarItems>

ContentPage.ToolbarItems je kolekce obsahující tlačítka, která mají být v Toolbaru zobrazena. ToolbarItem pak představuje konkrétní tlačítko. Vlastnost Name obsahuje popisek. Order určuje, zda se jedná o tlačítko, které má být zobrazeno vždy nebo až po rozbalení toolbar menu. Icon říká, jaká má být použita ikona.

Pro práci s ikonami jsou tu dvě možnosti. Buď můžete mít obrázek vložený přímo ve společném (Portable) projektu. V tomto případě je pro všechny platformy stejný a ve stejném rozlišení. Druhou možností je vložit obrázek do aplikace několikrát, a to do platformě závislých projektů. Díky tomu můžete mít nejen různé obrázky pro různé platformy, ale také můžete využít nativní mechanismy pro použití ikon na různých displejích. Vaše aplikace pak na žádném displeji nebude obsahovat rozmazané ikonky. My jsme zvolili možnost číslo dvě. Všechny ikony pojmenujte stejně (v tomto případě about.png) a můžete je vložit do příslušných projektů. Na Androidu je to složka Resources\drawable, Resources\drawable-mdpi atd. Na iOS vložte obrázky do složky Resources a ve WP projektu přímo do kořenové složky. Je potřeba dát si pozor na vlastnost Build Action jednotlivých souborů. Klikněte na ikonu a přejděte na záložku Properties. Zde můžete tuto vlastnost nastavovat. Pro WP musí být nastavena na Content, pro iOS BundleResource a na Androidu AndroidResource.

Stránka O aplikaci

Stejně jako když jsme přidávali MainPage.xaml přidáme i AboutAppPage.xaml a do konstruktoru v behind kódu umístíme stejnou úpravu vlastnosti Title jako na předchozí stránce.

Po vytvoření přidáme na stránku MainPage.xaml přechod do AboutAppPage.xaml:


private void AboutApp_Click(object sender, EventArgs e)
{
    (App.Current.MainPage as NavigationPage).PushAsync(new AboutAppPage());
}
     

Poté se můžeme pustit do definice View:


<ContentPage.Title>O aplikaci</ContentPage.Title>

<ScrollView>
<Grid Padding="20, 0, 20, 0">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>

<Image Grid.Row="0" Grid.Column="1" Source="logo.png" />
<Label Grid.Row="1" Grid.ColumnSpan="3" Style="{StaticResource Label}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" Text="Aplikace občanka slouží k ověření, zda je občanský průkaz evidován v databázi neplatných údajů Ministerstva vnitra ČR. Výsledek ověření má pouze informativní charakter."/>
<StackLayout Padding="20, 0, 20, 0" Grid.Row="3" Grid.ColumnSpan="3" Spacing="15">

</StackLayout>
<Label Grid.Row="5" Grid.ColumnSpan="3" Text="copyright © 2016 Skeleton Software s.r.o." HorizontalTextAlignment="Center" Style="{StaticResource Label}"/>
</Grid>
</ScrollView>

Tady už pro uspořádání komponent nepoužíváme jen základní StackLayout, ale i složitější layouty. Úplně na vrchu celé struktury je ScrollView. To zajišťuje, že náš obsah nebude limitován velikostí displeje, ale uživatel jím bude moci scrollovat. V něm je vnořený GridLayout, což je vlastně tabulka s různou velikostí sloupců a řádků, do kterých jednotlivé komponenty vkládáme. Nejprve si definujeme všechny řádky a sloupce, které má tabulka obsahovat a nastavíme jim jejich výšku a šířku. Hodnota auto znamená že sloupec/řádek bude mít velikost určenou svým obsahem. Oproti tomu * znamená, že se má roztáhnout co nejvíce to jde. Pokud máme několik sloupců/řádků s *, můžeme pomocí konstanty umístěné před hvězdičku nastavovat jejich poměr. To se hodí především pro dobrý vzhled vaší stránky na co největším počtu displejů nebo pokud chcete snadno obsluhovat rotaci displeje. Komponenty přiřazujeme do jednotlivých buněk pomocí vlastností Grid.Row a Grid.Column.

Další novinkou je Image. Ten slouží k zobrazování obrázků. Soubor vložíme, stejně jako ikonu pro tlačítko, do jednotlivých projektů. Vlastnosti Source nastavíme jeho název. Komponentě Label přibyla nová vlastnost HorizontalTextAligment. Ta určuje, jak má být text zarovnán.

Nyní nám zbývá už jen do připraveného StackLayoutu doplnit kontaktní údaje. Musí se zajistit, aby se po kliknutí na tyto údaje spustilo buď vytáčení telefonního čísla, webový prohlížeč nebo emailový klient.


 <Label Text="{Binding Web}" HorizontalTextAlignment="Start" TextColor="#8BAC18" Style="{StaticResource Label}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding WebLinkCommand}"/>
</Label.GestureRecognizers>
</Label>

<Label Text="{Binding Email}" HorizontalTextAlignment="Start" TextColor="#8BAC18" Style="{StaticResource Label}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EmailCommand}"/>
</Label.GestureRecognizers>
</Label>

<Label Text="{Binding PhoneNumber}" HorizontalTextAlignment="Start" TextColor="#8BAC18" Style="{StaticResource Label}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding PhoneNumberCommand}" CommandParameter="{Binding PhoneNumber}"/>
</Label.GestureRecognizers>
</Label>

<Label Text="{Binding MobileNumber}" HorizontalTextAlignment="Start" TextColor="#8BAC18" Style="{StaticResource Label}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding PhoneNumberCommand}" CommandParameter="{Binding MobileNumber}"/>
</Label.GestureRecognizers>
</Label>

Tady nám přibyly dvě novinky. Jednou z nich je použití slovíčka Binding. Jak funguje binding a MVVM je nad rámec tohoto článku. Nicméně je to velmi užitečný nástroj a v Xamarin.Forms ho lze využívat. Druhou novinkou je použití GestureRecognizeru. Pokud chceme snímat nějaká gesta provedená uživatelem nad komponentou nebo potřebujeme detekovat kliknutí na prvek, který nemá událost Clicked, lze toho docílit právě pomocí různých typů GestureRecognizer. V našem případě je to TapGestureRecognizer, který snímá kliknutí na komponentu. Do vlastnosti Command je bindován objekt, kterému při jeho vytváření přiřadíme akci. Ta se má po kliknutí provést. CommandParameter slouží k tomu, pokud chceme do akce předat nějaký parametr. V případe PhoneNumberCommand je to telefonní číslo, jenž má být po kliknutí vytočeno.

Aby binding fungoval, je potřeba vytvořit ViewModel a v něm definovat všechny potřebné vlastnosti. Do společného projektu si tedy přidáme složku ViewModels. V této složce umístíme novou třídu s názvem ContactsViewModel.cs. Pokud se data mění, měl by implementovat interface INotifyPropertyChanged. V našem případě to ale není nutné, jelikož jsou data statická.


public ContactsViewModel()
{
    Web = "www.skeleton.cz";
    Email = "info@skeleton.cz";
    PhoneNumber = "+420 377 477 731";
    MobileNumber = "+420 725 517 597";
    WebLinkCommand = new Command(WebLink_Click);
    EmailCommand = new Command(Email_Click);
    PhoneNumberCommand = new Command(PhoneNumber_Click);
}

public string Web { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string MobileNumber { get; set; }

public ICommand WebLinkCommand { private set; get; }
public ICommand EmailCommand { private set; get; }
public ICommand PhoneNumberCommand { private set; get; }
    

Názvy vlastností musí odpovídat názvům uvedeným v definici View za slovíčkem Binding. V inicializaci PhoneNumberCommandu si všimněte, že je použit generický Command namísto klasického. To nám umožňuje definovat typ dat, která chceme do akce předávat. Nyní musíme obsloužit kliknutí na jednotlivé kontaktní údaje.


private void PhoneNumber_Click(string number)
{
    Device.OpenUri(new Uri($"tel:{number}"));
}

private void Email_Click(object obj)
{
    Device.OpenUri(new Uri($"mailto:{Email}"));
}

private void WebLink_Click(object obj)
{
    Device.OpenUri(new Uri($"http://{Web}"));
}
    

Jak vidíte, díky použití generického Commandu je parametr metody PhoneNumber_Click typu string a ne object. Pro vytočení čísla, otevření emailu nebo zobrazení webu stačí vytvořit URI a to pomocí třídy Device otevřít. Xamarin.Forms a operační systém už se o zbytek postarají sami.

Poslední věc, kterou zbývá udělat, je přiřadit náš ViewModel stránce AboutAppPage.xaml. Nejprve musíme do stránky includovat namespace, v němž se ViewModel nachází, a poté nastavit BindingContext


<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Skeleton.Mobile.IdentityCardValidator.Pages.AboutAppPage"
xmlns:local="clr-namespace:Skeleton.Mobile.IdentityCardValidator.Extensions;assembly=IdentityCardValidator"
xmlns:viewModels="clr-namespace:Skeleton.Mobile.IdentityCardValidator.ViewModels;assembly=IdentityCardValidator"
BindingContext="{viewModels:ContactsViewModel}"
Padding="0, 0, 0, 20">

Vytvořená ukázková aplikace

AndroidStáhnout  Windows Phone Stáhnout  Android Stáhnout

Stáhnout zdrojové kódy (431 kB)

Závěr

V několika příštích článcích se budeme věnovat klasickému Xamarinu. Například operacím na pozadí, push notifikacím atd.

Nabídka práce

job_mobile

.NET programátor mobilních aplikací

Více informací

Vyjádření našich klientů

Aktivní a přemýšliví programátoři, spolehlivé projektové řízení, dodržené termíny. Profesionální spolupráce.

Alza.cz
Ing. Hana Žáková - Senior business developer

Více citací

Facebook

Úvod | Služby | Produkty | Reference | Kontakty | Přihlásit |

 Zpracování osobních údajů

Copyright © 2019 Skeleton Software s.r.o. | Všechna práva vyhrazena.