Tvorba aplikací pro Android

09

Tvorba menu

An­droid samozřejmě umožňuje přiřadit ap­likacím menu. V této kapitole si ukážeme základní pos­tup při vytvoření menu voleb. Zmíníme také tvor­bu pod­menu a ošetření výběru položky z menu. Pro de­tail­nější práci s menu (sdružování do skupin, výčet at­ributů pro položky menu, aj.) uvede­me pro zájemce od­kazy. V další kapitole si pak vyz­koušíme vytvoření kon­textového menu.


An­droid umožňuje vytvořit tři základní druhy menu

  1. Menu voleb

  2. Kon­textové menu, které se otevírá nejčastěji podržením prstu na prvku (wid­get, resp. ter­minologií ap­likací pro An­droid view – tlačítko, tex­tové pole,…), který má toto menu přiřazeno.

  3. Popup menu, které se zob­razuje jako svislý sez­nam jedno­tlivých položek.

Všechny typy menu pra­cují velmi podobně, hlavní rozdíl spočívá v plnění a získání in­for­mace o vyb­raných volbách.


Menu voleb (opt­ions menu)

Do verze An­droid 3.0 (API level 11) bylo menu vyvoláváno speciálním hardwarovým tlačítkem (tři tečky nebo čárky) a zob­razovalo se jako maximálně šest tlačítek uspořádaných v mřížce 2 × 3. Mělo-li menu více položek, šesté tlačítko bylo tvaru šipky, jehož účelem bylo zob­razit zbylé položky menu tak, aby uživatel viděl všechny najed­nou.



Obrázek 1 – menu se šesti tlačítky


Od verze An­droid 3.0 se menu ob­jevuje v panelu akcí (pokud je přítomno), případně lze dle nas­tav­ení vyvolat klik­nutím na příslušnou ikonu.


Tvor­bu základního menu voleb si ukážeme na jedno­duc­hém příkladu. Budeme chtít vytvořit menu o čtyřech položkách „Info“, „Kon­takt“, „Sdílet“ , „Nas­tav­ení“.


Bude výhodné, když pro první příklad použijeme při vytváření pro­jek­tu šab­lonu Blank Ac­tiv­ity, která už má základ menu nac­hystán. Jak ale rychle zjistíme, menu si snad­no přidáme i pokud jsme použili při vytváření pro­jek­tu Empty Ac­tiv­ity.


De­finice jedno­tlivých položek menu se provádí nejčastěji přes XML soubor­(y)1, který je uložen ve složce res/menu2. Jedno­tlivé názvy položek menu si nas­tavíme v souboru strings.xml ve složce re­s/values.

<resources>
    <string name="app_name">Menu voleb</string>
    <string name="menu_info">Info</string>
    <string name="menu_kontakt">Kontakt</string>
    <string name="menu_sdilet">Sdílet</string>
    <string name="menu_nastav">Nastavení</string>
</resources>

Obrázek 2 – soubor strings.xml


Otevřeme soubormenu_­main.xml a přidáme první položku menu „Info“. An­droid Studio již vytvořilo ukázku jedné volby, proto ji pro náš příklad stačí přepsat.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/menu_info" android:title="@string/menu_info"
    android:orderInCategory="100" android:showAsAction="never"/>
</menu>

Obrázek 3 – soubor menu_­main.xml, zápis jedné položky menu


Jak vidíme ze vzoru, každá položka menu je zapsána tagem <item/>. Jedno­tlivé at­ributy tohoto tagu určují další vlastnos­ti voleb. Mezi nej­používanější patří:

  • android:id – přiřazení iden­tifikátoru k položce menu, pomocí něhož se budeme moci odvolávat na tuto volbu.

  • android:title – načtení názvu položky ze souboru strings.xml.

  • android:orderInCategory – určuje pořadí položek v sez­namu, čím menší číslo, tím více vlevo či nahoře.

  • android:showAsAction – určuje, kdy bude položka menu viditelná.

    • always – položka se umístí na panel akcí.

    • ifRoom – položka se umístí na panel akcí, pokud je zde místo. Před­nost mají položky s menším číslem orderInCategory.

    • never – položka se nikdy neob­jeví na panelu akcí, je přístupná přes ikonu menu.


  • android:icon – načtení obrázku položky. Ikona se nejčastěji ukládá do složky re­s/draw­able.

  • android:checkable – určení, zda-li můžeme položku zaškrtnout (true, false).

  • android:alphabeticShortcut – znaková klávesová zkrat­ka.

  • android:numericShortcut – číslicová klávesová zkrat­ka.



Tip




Doplňme si do souboru main_menu.xml zbylé 3 hod­noty voleb:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/menu_info" android:title="@string/menu_info"
    android:orderInCategory="100" android:showAsAction="never"/>
<item android:id="@+id/menu_kontakt" android:title="@string/menu_kontakt"
    android:orderInCategory="100" android:showAsAction="never"  />
<item android:id="@+id/menu_sdilet" android:title="@string/menu_sdilet"
    android:orderInCategory="100" android:showAsAction="never"  />
<item android:id="@+id/menu_nastav" android:title="@string/menu_nastav"
    android:orderInCategory="100" android:showAsAction="never" />
</menu>

Obrázek 4 – kompletní kód pro menu se 4 položkami


Je­likož jsme navolili všechny at­ributy android:showAsAction na hod­notu „never” zůstávají jedno­tlivé volby skryty a objeví se až při klik­nutí na ikonu menu (tři tečky či čárky). Pokud nas­tavíme prvním dvou položkám tento at­ribut na „always” nebo „ifRoom”, uvidíme tyto volby ihned, zatímco zbylé dvě zůstávají skryté.

Obrázek 5 –





Tip



Zob­raz­ení menu v ap­likaci

Výhodou An­droid Studia je, že kód pro použití námi vytvořeného menu, přidává do ak­tiv­ity auto­matic­ky. V souboru java/<nazev_baliku>/MainAc­tiv­ity je přidána metoda public boolean onCreateOptionsMenu(Menu menu).

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

V případě, že by se náš soubor s menu (menu_­main.xml) jmenov­al jinak, přepíšeme pouze v metodě inflate iden­tifikátor tohoto souboru (například mojemenu, pokud se bude soubor jmenovat mojemenu.xml).


Ošetření výběru položky menu

Pokud chceme rea­govat na uživatelův výběr položky v menu, přek­ryjeme si metodu public boolean onOptionsItemSelected (MenuItem item). Tato metoda nám pro­střed­nictvím para­met­ru MenuItem item předává in­for­maci, na kterou položku menu bylo klik­nuto. Díky metodě getItemId() zjistíme číslo iden­tifikátoru dané položky – to jsme si navolili v souboru main_menu.xml. Po klik­nutí na položku menu Info můžeme tak třeba zob­razit in­for­mační bub­linu o ap­likaci.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId(); //zjištení identifikátoru zmačklé položky v menu
    if(id == R.id.menu_info)    //porovnání zjištěného identifikátoru s identifikátorem položky INFO
    {  //zobrazení informační bubliny
        Toast.makeText(this, "Aplikace na ukázku při vytváření menu", Toast.LENGTH_LONG).show();
    }
    return super.onOptionsItemSelected(item);
}

Pokud chceme provést ošetření všech položek, využijeme větvení podmínky if – else, případně konstruk­ce switch - case


Pos­tup vytvoření menu - shrnutí

  1. Spusťte vývojové prostředí An­droid Studio, pro­jekt nazvěte „Menu voleb“.

  2. Vyber­te kon­figuraci pro verzi An­droid 3.0 a vyšší.

  3. Otevřete ve složce re­s/values soubor strings.xml a přes tag <string> </string> doplňte názvy položek v menu.

  4. Otevřete ve složce res/menu soubor main_menu.xml a nadefinuj­te si přes tag <item/> položky v menu. Vyz­koušej­te si jedno­tlivé možnosti nas­tav­ení. Zkus­te například jednu položku menu zob­razit obrázkem.

  5. Otevřete třídu MainAc­tiv­ity a proveďte ošetření jedno­tlivých položek.

  6. Spusťte na pro­jekt na svém zařízení nebo virtuálním zařízení (VD) a otes­tujte.

Vytvoření pod­menu

V předchozí části jsme si ukázali vytvoření menu voleb, které se skládalo ze čtyř položek na stejné úrovni. Nyní budeme chtít vytvořit pod­menu položky Info tak, aby nabízela další dvě volby – In­for­maci o auto­roviIn­for­maci o ap­likaci. Určitě tušíte, že si budeme muset opět pohrát se souborem main_menu.xml. Nejprve ale doplňme nové názvy položek do souboru strings.xml.

<resources>
    <string name="app_name">Menu voleb</string>
    <string name="menu_info">Info</string>
    <string name="menu_kontakt">Kontakt</string>
    <string name="menu_sdilet">Sdílet</string>
    <string name="menu_nastav">Nastavení</string>
    <string name="pod_info_it1">Informace o autorovi</string>
    <string name="pod_info_it2">Informace o programu</string>
</resources>

Přejděme do souboru main_menu.xml a up­ravme ho. Pokud chceme využít u položky Info pod­menu, využijeme párového tagu <item> a do něj si de­finujeme další menu. Tedy:

  1. Nah­radíme nepárový tag <item/> u položky Info za párový tag <item> </item>

  2. Do něj si nadefinujeme nové menu pomocí tagu <menu> </menu>.

  3. Mezi tyto značky vložíme opět nepárové tagy <item/> , které vytvoří další dvě položky v pod­menu.

Soubor main_menu.xml bude tedy vypadat takto:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item android:id="@+id/menu_info" android:title="@string/menu_info"
        android:orderInCategory="100" android:showAsAction="always">
        <menu>
            <item android:id="@+id/pod_info" android:title="@string/pod_info_it1"
                android:orderInCategory="100" android:showAsAction="never"/>
            <item android:id="@+id/pod_info2" android:title="@string/pod_info_it2"
                android:orderInCategory="100" android:showAsAction="never"/>
        </menu>
    </item>
    <item android:id="@+id/menu_kontakt" android:title="@string/menu_kontakt"
        android:orderInCategory="100" android:showAsAction="always"  />
    <item android:id="@+id/menu_sdilet" android:title="@string/menu_sdilet"
        android:orderInCategory="100" android:showAsAction="never"  />
    <item android:id="@+id/menu_nastav" android:title="@string/menu_nastav"
        android:orderInCategory="100" android:showAsAction="never" />
</menu>

Po klik­nutí na INFO se objeví sez­nam vytvořený v pod­menu:


Obrázek 7 –


Všimněte si, že in­for­mační bub­lina (Toast) se stále zob­razuje už při klik­nutí na volbu Info. Rea­kci na volby pod­menu upravíme stejně jako u voleb menu. Na všechny volby (pod­menu i menu) od­kazujeme pomocí je­jich ID.


Up­rav­ený kód metody onOptionsItemSelected(…) bude vypadat takto:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    //noinspection SimplifiableIfStatement
    if (id == R.id.pod_info) {
        Toast.makeText(this, "Aplikace na ukázku při vytváření menu", Toast.LENGTH_LONG).show();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Úkol: Doplňte menu do pro­jek­tu Můj pestrý život

Doplňte menu voleb do pro­jek­tu Můj pestrý život z předchozích kapitol. V menu budou volby Znovu načti (zahodí stávající data a načte ze souboru původní verzi) a Ulož (uloží stávající data do souboru).


V pro­jek­tu již máme přip­raveny metody Data.nactiData(...)DataKlientu.ulozData(…). Stačí tedy vytvořit menu voleb a následně tyto metody zavolat, kdykoli uživatel zvolí odpovídající položku menu.


Protože jsme v tomto pro­jek­tu začínali od Empty Ac­tiv­ity, budeme si muset vytvořit pod adresář res/menu i soubor main_menu.xml. Obojí zařídíme v okně Pro­ject An­droid Studia:

  • Klik­neme pravým tlačítkem na složku res a vybereme New→ An­droid Re­sour­ce Di­rec­to­ry a vybereme typ menu.

  • Dále klik­neme pravým tlačítkem na nově vytvořenou složku a zvolíme New→ Menu Re­sour­ce File. Jako typ zadáme Main menu.

Shrnutí:

  • De­finování položek menu provádíme v XML souboru uloženém v adresáři res/menu.

  • Položku menu vytvoříme pomocí nepárového tagu <item/>.

  • Chceme-li vytvořit pod­menu, nah­radíme nepárový tag <item/> za párový a uvnitř de­finujeme nové menu pomocí párového tagu <menu> a nepárových tagů <item/>.

  • Provázání XML souboru menu s ap­likací se stará metoda onCreateOptionsMenu(Menu menu) a metoda getMenuInflater.inflate(...), ve které předáme iden­tifikátor souboru s menu.

  • Díky metodě onOptionsItemSelected(MenuItem item)můžeme ošetřit, zda uživatel vybr­al určitou volbu v menu či pod­menu. ID zvol­ené položky získáme pomocí metody item.getItemId(). ID je číselné a lze tedy porov­návat s hod­notami at­ributů android:id jedno­tlivých voleb pomocí příkazů if či switch.


1 Druhou možností je zap­sat přímo kód do metody onCreateOptionsMenu(Menu menu) – touto možností se ale zabývat nebudeme

2 Některá vývojová prostředí složku menu nevytváří, neboj­te se ji proto ve složce res vytvořit ručně, stejně tak jako soubor menu.xml