9. C# aplikace pro Android a práce s animacemi

Téma

 C# aplikace pro Android a práce s animacemi

Tematický celek

 Tvorba mobilní Android aplikace v jazyce C#

Motivační rámec

 Když už jsme si pohráli s klasickými ovládacími prvky, vyzkoušíme si teď vytvořit jednoduchou animaci. (Aneb je to barevné a hýbá se to!)

Počet žáků

 15

Věk žáků

 16-18

Pomůcky

  PC, tablet nebo emulátor OS Android. Vývojové prostředí SharpDevelop z balíčku dot42.

Stručný popis aktivity s využitím přístroje

 Studenti pomocí vývojového prostředí sharpDevelop vytvoří aplikaci, generující animaci pohybujícího se kruhu.

Vhodné místo

 Běžná počítačová učebna vybavená operačním systémem Windows.

Cíle aktivity

 Studenti budou schopni vytvořit Android aplikaci, která bude obsahovat jednoduchou animaci libovolného geometrického tvaru, například kruhu.

Rozvíjené kompetence

 Kompetence k učení, k řešení problémů

Předchozí znalosti

 C# aplikace pro Android s grafickými interaktivními prvky

Časový plán

Fáze činnosti s přístrojem

Metody a formy, motivace

10 minut

Spuštění počítače, založení nového projektu a odstranění přebytečných prvků.

Samostatná práce nebo práce ve skupině

35 minut

Tvorba nového panelu, na kterém se bude pohybovat zelený kruh s nápisem uvnitř. Následné spuštění a testování aplikace.

Samostatná práce nebo práce ve skupině

Hodnocení

 Bez hodnocení. Studenti budou hodnoceni až po tvorbě vlastních aplikací.

Návaznosti

 Na tuto aktivitu navazuje aktivita Závěrečné poznámky a zdroje

Zadání:

1. Vytvořte nový projekt typu dot42.

2. Vyčistěte ho od zbytečností, včetně MainLayout.xml, tentokrát nebude potřeba.

3. Nastavte aplikaci na celou obrazovku bez nadpisu.

4. Vytvořte panel s modrým pozadím, na kterém bude probíhat animace pohybujícího se zeleného kruhu s nápisem uvnitř.

5. Aplikaci spusťte a vyzkoušejte.

Postup:

Nejprve je třeba vytvořit nový projekt a vyčistit ho od zbytečností, což už jsme dělali několikrát. Bylo by také dobré nastavit aplikaci jméno, jako jsme si ukázali v předchozí kapitole. Co však tentokrát uděláme jinak je, že odstraníme také MainLayout.xml, který nám normálně umožňuje stavět aplikaci pomocí interaktivních grafických komponent. Na animaci a vykreslování elementární grafiky však nestačí, na to budeme potřebovat nějaký panel, který bude potomkem třídy SurfaceView. To bychom ale předbíhali, nejprve je třeba upravit hlavní vygenerovaný soubor a to je MainActivity.cs. Na následujících obrázcích bude ilustrováno, jak na to. Pro demonstraci byly zvoleny obrázky, hlavně proto, že na nich je dobře graficky zvýrazněn zdrojový kód, což v těle kurzu tak jednoduše nelze.

Jak vidíme na obrázku, zas tolik se nám to nezměnilo. Přibyla nám funkce RequestWindowFeature, která zajišťuje to, aby se aplikace spustila v určitém náhledovém režimu. V našem případě chceme aplikaci na full screen bez nadpisu, jako to můžeme vidět v předchozí aktivitě. Vzhledem k tomu, že chceme mít modrou plochu na celé obrazovce, nadpis s názvem aplikace by nám tam zbytečně překážel a ubíral prostor. Poté použijeme naši již známou funkci SetContentView, abychom nastavili určitou grafiku jako hlavní obsah aplikace. Tentokrát však nepoužijeme layout vytvořený v MainLayout.xml, ale námi vytvořený nový panel, který je potomkem třídy SurfaceView. Na následujících obrázcích si pak ukážeme funkcionalitu, kterou ho naplníme.

Na tomto obrázku je vidět definice samotné třídy Panel. Jak vidíme, je potomkem třídy SurfaceView, která je specificky navržena, aby poskytla aplikaci co nejlepší možnosti v oblasti grafiky a kreslení na "plátno" neboli canvas. Třída Panel pak zároveň implementuje dvě rozhraní. ISurfaceHolder_ICallback je rozhraní, které umožňuje programu přijímat informace o změnách na "povrchu" aplikace.  IRunnable je pak klasické rozhraní, které umožňuje třídě běžet v samostatném vlákně.

Dále pak nadefinujeme několik uživatelských proměnných. Proměnné poloha a rozdil se budou týkat polohy a směru pohybu našeho kruhu a proměnná bezi bude rozhodovat o tom, zda se bude ve vlákně přepočítávat poloha, a bude hlídat, zda aplikace už neskončila. Poslední proměnná holder bude v sobě udržovat odkaz na grafický "povrch" aplikace, na kterém se bude vykreslovat naše grafika.

A jako poslední v této fázi je třeba nadefinovat konstruktor Panelu, ve kterém je třeba získat aktuální holder (pomocí funkce GetHolder) a spojit ho s touto instancí třídy Panel funkcí AddCallback. To zaručí, že změny vycházející z této instance panelu se do grafiky skutečně promítnou.

Dále je třeba vytvořit funkce vyžádované díky implementaci našich dvou rozhraní.

Všechny tyto funkce začínající slovem surface jsou vyžadovány rozhraním ISurfaceHolder_ICallback a všechny se týkají samotného povrchu aplikace. SurfaceCreated se zavolá v okamžiku vytvoření grafického povrchu. V tu chvíli už můžeme nastavit proměnnou bezi na true, protože je načase začít vykreslovat animaci. Zároveň pak vytvoříme nové vlákno, ve kterém se bude animace připravovat a vykreslovat a toto vlákno nastartujeme. Mechanika je stejná jako v jakékoliv jiné C# aplikaci. Ve funkci SurfaceDetroyed vykreslování zase naopak vypneme, protože aplikace byla zavřena a povrch smazán. Funkce SurfaceChanged si nevšímáme, protože pro ni v naší aplikaci nemáme využití. Nicméně v programu se musí nacházet, protože její užití je vynuceno rozhraním.

Poslední funkce vynucená rozhraním je pro nás klíčová. Jedná se o funkci Run, kterou využívá rozhraní IRunnable. Tato funkce se spouští, hned jak je nastartováno vlákno, ve kterém běží, a jakmile doběhne, vlákno se ukončí. Ve většině případů se v něm nachází nějaký cyklus, který dokola opakuje určité akce. V našem případě opakujeme cyklus, dokud aplikace běží. Nejprve pomocí funkce LockCanvas zamkneme plátno pro jiné procesy a systému tím dáme najevo, že se chystáme měnit samotné pixely na něm, jinak řečeno, budeme na něj něco kreslit. Poté zavoláme námi vytvořenou funkci DoDraw (probereme ji dále), která se postará o samotné vykreslení grafiky na plátno. Pak už jen stačí pomocí funkce UnlockCanvasAndPost plátno odemknout a zobrazit na něm naše změny. Dál už stačí jen naše vlákno na chvíli uspat pomocí Thread.Sleep, abychom simulovali plynulý pohyb kruhu, a funkcionalita je na světě. Teď už nám stačí jen dopsat funkci DoDraw, která se postará o samotné umístění grafických prvků.

V první části je jednoduchá mechanika, která řeší, zda se kruh bude zrovna pohybovat směrem doleva nebo doprava. Jakmile je poloha rozhodnuta, přichází samotné vykreslování grafiky. Nejprve zabarvíme celé plátno modrou barvou pomocí DrawColor(Color.BLUE). Poté vytvoříme nový štětec typu Paint, kterým budeme jednotlivé prvky kreslit. Pomocí SetTextAlign(Paint.Align.CENTER) nastavíme zarovnávání textu psaného naším štětcem na střed, což použijeme později při vpisování textu do našeho kruhu. Dříve než něco vykreslíme, vždy nastavíme barvu daného objektu pomocí funkce SetColor. V případě kruhu to bude zelená a v případě textu pak červená. Na samotné objekty pak použijeme funkce DrawCircle v případě kruhu a DrawText v případě textu. K umístění pak použijeme souřadnice vygenerované s pomocí naší proměnné poloha. A jako jeden z parametrů funkcí také přidáme námi vygenerovaný štětec. Takto zapsaný kód je vcelku jednoznačný a intuitivní. Jakmile jsme tedy dopsali funkci DoDraw, nic už nám nebrání aplikaci spustit a podívat se na výsledek.   

A na následujícím videu je pak už vidět samotná hotová aplikace. Omluvte prosím cukání v pohybu kruhu, je to způsobeno nahráváním videa z obrazovky, které nedokáže snímat tak rychle, aby byl pohyb plynulý. V samotné aplikaci se kruh pohybuje velmi plynule.