J2ME v příkladech – tvorba menu

21. března 2003

V předchozím článku jste se seznámili se základy psaní aplikací pro mobilní telefony neboli midletů. Kromě tohoto úvodu obsahoval první krok v tvorbě midletů a sice úvodní obrazovky. V tomto článku se naučíte vytvořit další část aplikace – menu.

Co to je, co obsahuje a jak funguje

Základní nabídka aplikace neboli menu je jakýsi souhrn možností, které aplikace nabízí uživateli. Obsahuje veškeré uživatelsky dostupné funkce aplikace, její nastavení, prvky pro vkládání dat a volby pro formátování výstupů, příkazy pro přechody mezi stavy aplikace a různé doplňkové informace, například o původu aplikace a jejím autorovi. Je proto nutné se před tvorbou menu důkladně zamyslet nad jeho položkami a věnovat mu maximální péči, aby se uživatel orientoval v aplikaci bez větších problémů a aby beze zbytku využil možnosti, které mu aplikace poskytuje.

Způsobů, jak vytvořit menu v mobilní aplikaci, je hned několik. Základní rozdělení je možno provést podle použitých komponent, a to na vysokoúrovňové a nízkoúrovňové. Základní informace o těchto komponentách a jejich rozdílech a použití najdete v článku J2ME v kostce – kreslíme na displej.

Tvorba menu za použití vysokoúrovňových komponent

Tím prvním způsobem je vytvoření skupiny příkazů neboli prvků třídy Command. Interpretace této třídy je plně závislá na konkrétní implementaci Javy specifické pro různé druhy mobilních telefonů. To nás sice omezuje ve formě zobrazení, kterou nemáme možnost blíže ovlivnit, ale zase na druhou stranu se nemusíme starat o funkčnost menu, stačí nám podle volby příkazu z jejich seznamu zavolat příslušnou metodu, která provede zvolený postup nebo funkci.

Třída Command má jen jeden konstruktor, následující příklad ukazuje jeho použití :

Command cmd_about = new Command(„Info“, Command.SCREEN, 1);

Konstruktor obsahuje tři parametry:

  • Název je řetězec, který popisuje daný příkaz. Je umístěn buď jako označení funkčního tlačítka na displeji nebo je prvek nabídky více příkazů. Nemá žádnou další funkci, jeho hodnotu můžeme zjistit metodou getLabel();.
  • Typ příkazu předurčuje jeho účel, k dispozici máme několik předdefinovaných typů: BACK, CANCEL, EXIT, HELP, ITEM, OK, SCREEN a STOP. Pro náš účel tvorby menu je nejvhodnější použít typ SCREEN, který je určen pro tvorbu seznamu příkazů na „obrazovce“ mobilního telefonu neboli dipleji.
  • Priorita je celé číslo, které definuje důležitost příkazu vzhledem k ostatním příkazům na obrazovce. Čím nižší hodnota, tím vyšší priorita, 1 znamená nejvyšší prioritu. V praxi to znamená, že ze seznamu několika příkazů budou k funkčním tlačítkům na telefonu přiřazeny nejprve příkazy s vyšší prioritou, ostatní budou seřazeny v seznamu, který se otevírá až po uživatelském vstupu – typicky volbě Menu.

Použijeme aplikaci, kterou jsme vytvořili v minulém článku. Soubor Splash.java ponecháme beze změn. Soubor Abc.java bude navíc obsahovat vytvoření jednotlivých příkazů, které tvoří menu, jejich umístění na displej a zavolání příslušné metody při jejich výběru. Zdrojový kód bude vypadat následovně:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  Display disp;
  Command cmd_konec;
  Command cmd_nast;
  Command cmd_help;
  Command cmd_about;
  Canvas can;
  List lst_nast;
  String str_about;
  Form frm_about;
  public Abc() {
  // v konstruktoru třídy vytvoříme tlačítka které budou tvořit položky menu
    cmd_konec = new Command(„Konec“, Command.SCREEN, 1);
    cmd_nast = new Command(„Nastaveni“, Command.SCREEN, 2);
    cmd_about = new Command(„Info“, Command.SCREEN, 2);
  // toto je nabídka nastavení aplikace
    lst_nast = new List(„Nastaveni“, Choice.MULTIPLE);
    lst_nast.append(„Zvuk“, null);
    lst_nast.append(„Vibrace“, null);
  // vytvoříme řetězec s informací o aplikaci a umístíme ji na samostatný formulář
    str_about = „První MIDlet, verze 1.0, příklad ze serveru interval.cz“;
    frm_about = new Form(„Info“);
    frm_about.append(str_about);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    can = new Splash();
  // následně příkazy umístíme na obrazovku, jejich zobrazení podléhá jejich prioritě
  // navzdory tomu, že tlačítko pro ukončení aplikace jsme přidali jako poslední, je zobrazeno na prvním místě
    can.addCommand(cmd_nast);
    can.addCommand(cmd_about);
    can.addCommand(cmd_konec);
    can.setCommandListener(this);
    disp.setCurrent(can);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
  // zde vyhodnotíme výběr položky z nabídky a podle toho zavoláme příslušnou metodu
    if(d == can) { // pokud zjistíme, zda je příkaz volaný z úvodní obrazovky
      if(c == cmd_konec) { destroyApp(true); } // a pokud byl vybrán příkaz konec ukončíme aplikaci
      if(c == cmd_about) { info(); } // na příkaz about ukážeme informace o aplikaci
      if(c == cmd_nast) { nast(); } // a nebo při volbě nast nabídneme možnosti nastavení
    }
    if(d == lst_nast || d == frm_about) { // příkaz byl volán z nabidky Nastaveni nebo Info
      if(c == cmd_konec) { // ukončíme nastavování nabo info a vrátíme se na začátek – zobrazíme úvodní obrazovku
      disp = Display.getDisplay(this);
      disp.setCurrent(can);
      }
    }
  }
  public void info() {
  // zobrazíme info
      disp = Display.getDisplay(this);
      frm_about.addCommand(cmd_konec);
      frm_about.setCommandListener(this);
      disp.setCurrent(frm_about);
  }
  public void nast() {
    // zde vytvorime nabidku nastaveni aplikace
      disp = Display.getDisplay(this);
      lst_nast.addCommand(cmd_konec);
      lst_nast.setCommandListener(this);
      disp.setCurrent(lst_nast);
  }
}

Po zkompilování a vytvoření balíčku (JAD a JAR souboru) už jen zbývá nahrát aplikaci do mobilního telefonu a spustit. Máme vlastnoručně napsané menu ve vlastní aplikaci pro mobilní telefon. Na následujícím obrázku je vidět menu tvořené tímto způsobem na mobilním telefonu Siemens C55.

Menu vytvořené jako skupina příkazů
Menu vytvořené jako skupina příkazů – Siemens C55.

Tuto metodu tvorby menu bohužel nelze použít, pokud jako úvodní obrazovku použijeme potomka třídy FullCanvas, které je součástí implementace Javy v mobilních telefonech Nokia. Tato třída neumožňuje použití rozhraní CommandListener, takže pro vyvolání nabídky je nutno použít zachycení funkční klávesy pomocí metody keyPressed. Proto v tomto příkladu použijeme i pro mobilní telefony Nokia úvodní obrazovku odvozenou od třídy Canvas.

Další možnost, jak s použitím vysokoúrovňových komponent vytvořit uživatelsky přijatelné menu, je použití třídy List. Tato třída umožňuje vytvářet seznamy položek s možností volby. Způsoby výběru jsou tři: MULTIPLE – výběr libovolného počtu položek ze seznamu, EXCLUSIVE – je možno vybrat právě jen jednu položku ze seznamu, IMPLICIT – položka je vybrána v okamžiku, kdy je označena kurzorem. Pro tvorbu menu pomocí třídy List nás bude zajímat způsob výběru IMPLICIT. Opět použijeme třídu Abc:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  Display disp;
  Command cmd_nabidka;
  Canvas can;
  List lst_nast;
  List lst_menu;
  String str_about;
  Form frm_about;
  public Abc() {
    cmd_nabidka = new Command(„Nabidka“, Command.SCREEN, 1);
  // toto je nabídka nastavení aplikace
    lst_nast = new List(„Nastaveni“, Choice.MULTIPLE);
    lst_nast.append(„Zvuk“, null);
    lst_nast.append(„Vibrace“, null);
  // zde vytvoříme menu
    lst_menu = new List(„Menu“, Choice.IMPLICIT);
    lst_menu.append(„Konec“, null);
    lst_menu.append(„Nastaveni“, null);
    lst_menu.append(„Info“, null);
    str_about = „První MIDlet, verze 1.0, příklad ze serveru interval.cz“;
    frm_about = new Form(„Info“);
    frm_about.append(str_about);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    can = new Splash();
    can.addCommand(cmd_nabidka);
    can.setCommandListener(this);
    disp.setCurrent(can);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
      if(c == cmd_nabidka) { menu(); } // pokud byl vybrán příkaz nabídka zobrazíme menu
      if(d == lst_menu) { // pokud byl příkaz volán z obrazovky menu
        int vyber = lst_menu.getSelectedIndex(); // zjistíme která položka byla vybrána
        switch(vyber) { // a podle toho zavoláme příslušnou metodu
          case(0): destroyApp(true); break;
          case(1): nast(); break;
          case(2): info(); break;
        }
      }
    }
  public void info() {
    // zobrazíme info
      disp = Display.getDisplay(this);
      frm_about.addCommand(cmd_nabidka);
      frm_about.setCommandListener(this);
      disp.setCurrent(frm_about);
  }
  public void nast() {
    // zde vytvoříme nabídku nastavení aplikace
      disp = Display.getDisplay(this);
      lst_nast.addCommand(cmd_nabidka);
      lst_nast.setCommandListener(this);
      disp.setCurrent(lst_nast);
  }
  public void menu() {
      disp = Display.getDisplay(this);
      lst_menu.setCommandListener(this);
      disp.setCurrent(lst_menu);
  }
}

Vše už vypadá přijatelněji, podívejme se, jak si s tímto menu poradí telefon Siemens SL45i:

Menu vytvořené jako List.
Menu vytvořené jako List – Siemens SL45i.

Menu je už na první pohled jiné. Je to vlastně seznam položek nabídky, v okamžiku, kdy jednu z nabídek označíme kurzorem, je automaticky vybrána, proto když při stisku tlačítka volby zjistíme getSelectedIndex(), automaticky dostaneme index označené položky, a o to v menu jde.

Aby toto menu vypadalo opravdu hezky, můžeme využít jedné z možností, které nám třída List nabízí, a sice přidat k položkám nabídky obrázky, které ji doplní o grafické znázornění volby. Použité obrázky jsou černobílé, mají velikost 12 x 12 pixelů a jsou ve formátu PNG. Zvolená velikost a barevná hloubka nejlépe vyhovuje při použití v různých typech mobilních telefonů, samozřejmě je možno použít obrázky větší a barevné, zde ponechám prostor fantazii čtenáře. Následuje příklad jejich použití:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  Display disp;
  Command cmd_nabidka;
  Canvas can;
  List lst_nast;
  List lst_menu;
// obrázky pro použití v nabídce
  Image img_konec;
  Image img_info;
  Image img_nast;
  String str_about;
  Form frm_about;
  public Abc() {
  // v try – catch bloku vytvoříme obrázky ze souborů
    try {
      img_konec = Image.createImage(„/btn_konec.png“);
      img_info = Image.createImage(„/btn_info.png“);
      img_nast = Image.createImage(„/btn_nast.png“);
      } catch(Exception e) { }
    cmd_nabidka = new Command(„Nabidka“, Command.SCREEN, 1);
  // toto je nabidka nastaveni aplikace
    lst_nast = new List(„Nastaveni“, Choice.MULTIPLE);
    lst_nast.append(„Zvuk“, null);
    lst_nast.append(„Vibrace“, null);
  // zde vytvoříme menu
    lst_menu = new List(„Menu“, Choice.IMPLICIT);
    lst_menu.append(„Konec“, img_konec); // přídáme obrázky k položkám nabídky
    lst_menu.append(„Nastaveni“, img_nast);
    lst_menu.append(„Info“, img_info);
    str_about = „První MIDlet, verze 1.0, příklad ze serveru interval.cz“;
    frm_about = new Form(„Info“);
    frm_about.append(str_about);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    can = new Splash();
    can.addCommand(cmd_nabidka);
    can.setCommandListener(this);
    disp.setCurrent(can);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
      if(c == cmd_nabidka) { menu(); } // pokud byl vybrán příkaz nabidka zobrazime menu
      if(d == lst_menu) { // kliknutí je voláno z menu
        int vyber = lst_menu.getSelectedIndex(); // zjistíme která položka byla vybrána
        switch(vyber) {
          case(0): destroyApp(true); break;
          case(1): nast(); break;
          case(2): info(); break;
        }
      }
    }
  public void info() {
    // zobrazime info
      disp = Display.getDisplay(this);
      frm_about.addCommand(cmd_nabidka);
      frm_about.setCommandListener(this);
      disp.setCurrent(frm_about);
  }
  public void nast() {
    // zde vytvorime nabidku nastaveni aplikace
      disp = Display.getDisplay(this);
      lst_nast.addCommand(cmd_nabidka);
      lst_nast.setCommandListener(this);
      disp.setCurrent(lst_nast);
  }
  public void menu() {
      disp = Display.getDisplay(this);
      lst_menu.setCommandListener(this);
      disp.setCurrent(lst_menu);
  }
}

Zde je pro srovnání stejné menu jako v předchozím případě doplněné o obrázkové položky. Rozdíl je velký, menu vypadá opravdu profesionálně:

Menu vytvořené jako List s použitím obrázků.
Menu vytvořené jako List s použitím obrázků – Siemens SL45i.

Z následujících obrázků můžete zjistit, jak to vypadá na různých telefonech (Motorola i85s, Nokia 7210, Siemens S55 a Siemens MT50).

Motorola i85s

Nokia 7210

Siemens S55

Siemens MT50

Jak je vidět například mobilní telefony Nokia umožňují použití větších obrázků, v případě barevných displejů navíc i barevných. To je šance pro tvůrce aplikací, aby do obrázku dostali maximální informační hodnotu, která používání menu urychlí a zpříjemní. Použití takzvaných piktogramů v menu může dokonce smazat jazykovou bariéru a aplikace může být srozumitelná pro uživatele na celém světě.

Tak to bylo vytvoření uživatelské nabídky neboli menu za pomocí vysokoúrovňových komponent. Menší úpravou je jistě možné dosáhnout nabídky „na míru“ dané aplikaci tak, aby uživatel plně využil její možnosti.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Další článek haj
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *