Už jsme si ukázali, jak se tvoří úvodní obrazovka midletů a také jak se tvoří nabídka neboli menu pomocí vysokoúrovňových komponent. Nyní se naučíme tvořit menu pomocí nízkoúrovňových komponent se vším, co k tomu patří.

Jak to funguje a co tím dosáhneme?

Nyní už je nám jasné jak fungují vysokoúrovňové komponenty. Jejich zobrazení je závislé na konkrétní implementaci Javy v mobilním telefonu. Na jednu stranu nám to ušetří hodně práce a starostí s tím, aby vše fungovalo opravdu korektně a bez zádrhelů, ale na druhou stranu nás to celkem omezuje z hlediska kreativity a designu. Menu je sice funkční, ale je stejné jako v ostatních aplikacích na stejném typu mobilního telefonu, kde autor použil stejných komponent. Pokud toužíte po osobitém vzhledu své aplikace, musíte se pustit do nízkoúrovňových komponent.

Tento přístup k tvorbě menu spočívá v jeho vytvoření takříkajíc od píky. Pokud zvolíte tuto cestu, je třeba myslet na to, že máte prakticky neomezené možnosti, co se týče vzhledu a funkcionality menu, nesmíte ale zapomínat, že na vaši hlavu padá odpovědnost za jeho kompletní funkcionalitu. Je třeba postarat se o každičký detail, byť by to měl být jen posun kurzoru mezi jednotlivými položkami. Laicky řečeno, budete se starat o vykreslení každého pixelu „ručně“. Budete kreslit jednotlivé položky menu, ukazatel aktuálně zvolené položky, který budete zobrazovat tak, aby jeho poloha korespondovala s uživatelským vstupem. Budete „hlídat“ klávesy tak, aby při stisku zaznamenal uživatel požadovanou akci.

Na první pohled to vypadá opravdu náročně, ale opak může být pravdou. Pojďme se o tom přesvědčit. Pro názorné srovnávání lehce navážeme na menu z předešlé kapitoly a vytvoříme menu se stejnou funkcionalitou, ale s jiným vzhledem – výsledek budete moci srovnat sami.

Nejprve pár obrázků…

Nové menu bude mít velikost 101×64 pixelů, vejde se tedy na všechny telefony, které mají displej odpovídající velikosti. Použitý podklad bude černobílý, majitelé barevných mobilů si však mohou vytvořit podklad barevný a bez problémů ho v našem příkladu použít.

Jako první vytvoříme podklad menu. Bude buď černobílý nebo barevný, to podle dispozic mobilního telefonu. My si vytvoříme obě varianty v jedné aplikaci. Midlet totiž dokáže rozpoznat jestli je zobrazen na barevném nebo černobílém displeji, čehož využijeme a podle toho zobrazíme černobílý nebo barevný podklad:

Menu.png
Menu 101 x 64, formát PNG, černobílý.

Menu.png barevný
Menu 101 x 64, formát PNG, barevný.

Tyto obrázky budou sloužit jako podklad pro naše menu. Pro výběr jednotlivé položky nám poslouží kurzor, také namalovaný:

Cursor.png
Kurzor, obrázek PNG 9 x 15 pixelů.

Dále bude pod kurzorem zobrazen ještě popis vybrané funkce. To provedeme pomocí textové položky, vykreslené metodou drawString.

Kromě pohybu kurzoru, který budeme při stisku klávesy provádět, budeme také kontrolovat zvolenou položku nabídky. Tak budeme moci správně vyhodnotit volbu a zavolat vybranou metodu. Pro vyhodnocení stisknutých tlačítek jsem použil metodu keyPressed třídy Canvas, která vrací kód stisknuté klávesy. Kromě toho umí i vyhodnotit tzv. GAME ACTION kódy kláves. Jsou to kódy určené pro klávesy, u kterých výrobce předpokládal, že budou primárně používány k ovládání her. Bohužel rozdílná implementace Javy od různých výrobců v tomto spíše udělala zmatek a já jsem raději použil ovládání číselnými klávesami: 1 – doleva, 3 – doprava a 2 – výběr položky.

…a pak nějaký ten program

Použijeme opět třídu Abc.java. V tomto příkladu bude postrádat příkazy pro tvorbu menu, to nyní bude záležitost třídy Menu.java. Třída Abc.java obsahuje následující kód:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  Display disp;
  Command cmd_menu;
  Canvas can;
  List lst_nast;
  String str_about;
  Form frm_about;
  boolean barva;
  public Abc() {
    cmd_menu = new Command(„Menu“, Command.SCREEN, 1);
    lst_nast = new List(„Nastaveni“, Choice.MULTIPLE);
    lst_nast.append(„Zvuk“, null);
    lst_nast.append(„Vibrace“, 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() {
    menu();
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
      if(c == cmd_menu) { menu(); }
  }
  public void info() {
      disp = Display.getDisplay(this);
      frm_about.addCommand(cmd_menu);
      frm_about.setCommandListener(this);
      disp.setCurrent(frm_about);
  }
  public void nast() {
      disp = Display.getDisplay(this);
      lst_nast.addCommand(cmd_menu);
      lst_nast.setCommandListener(this);
      disp.setCurrent(lst_nast);
  }
  public void menu() {
      disp = Display.getDisplay(this);
      barva = disp.isColor();
      can = new Menu(this);
      disp.setCurrent(can);
  }
}

Jak sami vidíte neobsahuje nic zvláštního. Jediná věc, která je zde nová, je metoda isColor, která vrací true v případě barevného displeje nebo false v případě displeje černobílého. To, o čem je dnešní článek, je celé v třídě Menu.java. Obsahuje veškeré vykreslování, změnu vybraných položek a příkazy pro provedení vybrané akce.

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class Menu extends Canvas {
  Abc midlet;
  Image img_menu;
  Image img_cursor;
  int osa_x = 12;
  int vyber = 1; // index vybrane polozky
  String label;
  String str_menu;
  public Menu(Abc midlet) {
    this.midlet = midlet; // v konstruktoru pouzijeme odkaz na tridu Abc.java
    try {
    // podle typu displeje vybereme podklad
      if(midlet.barva) { str_menu = „/menu_c.png“; } else { str_menu = „/menu.png“; }
      img_menu = Image.createImage(str_menu);
      img_cursor = Image.createImage(„/cursor.png“); // a vytvorime v pameti obrazek kurzoru
      } catch(Exception e) { }
  }
  public void paint(Graphics g) {
    g.setColor(255, 255, 255);
    g.fillRect(0, 0, getWidth(), getHeight()); // nejprve vybarvime plochu bile
    g.drawImage(img_menu, 0, 0, g.TOP|g.LEFT); // a pak umistime nejprve podklad
    g.drawImage(img_cursor, osa_x, 35, g.TOP|g.LEFT); // nasledovany kruzorem, osa_x urcuje pozici
    switch(vyber) { // podle vybrane polozky zobrazime komentar
      case(1): label = „Konec“; break;
      case(2): label = „Nastaveni“; break;
      case(3): label = „Info“; break;
    }
    if(midlet.barva) { g.setColor(0, 0, 255); } else { g.setColor(0, 0, 0); }
    g.drawString(label, 35, 50, g.TOP|g.LEFT);
  }
  protected void keyPressed(int keyCode) { // udalost vyvolana pri stisku tlacitka
    switch(keyCode) {
      case(49): left(); break; // stisknuta klavesa 1 – kurzor doleva
      case(51): right(); break; // klavesa 3 – kurzor doprava
      case(50): proceed(); break; // klavesa 2 – vyber polozky
    }
  }
  public void left() {
      if(osa_x > 12) {
          osa_x = osa_x – 34;
          vyber = vyber – 1;
          repaint(); // vykresli podklad a kurzor na nove pozici
      } else {
          osa_x = 80;
          vyber = 3;
          repaint();
      }
  }
  public void right() {
      if(osa_x < 80) {
          osa_x = osa_x + 34;
          vyber = vyber + 1;
          repaint();
      } else {
          osa_x = 12;
          vyber = 1;
          repaint();
      }
  }
  public void proceed() {
    switch(vyber) { // zjistime vybranou akci a zavolame metodu
        case(1): midlet.destroyApp(true); break;
        case(2): midlet.nast(); break;
        case(3): midlet.info(); break;
    }
  }
}

Jak to vlastně pracuje?

Po spuštění vytvoří midlet instanci třídy Menu.java, kterou umístí na displej. Tato třída vykreslí na displej podklad menu, kurzor a popisek právě zvolené položky z nabídky. Dále zajišťuje „hlídání“ stisknutých tlačítek. Při stisknutí tlačítka 1 nebo 3 zavolá metodu left() nebo right() pro pohyb kurzoru. Tyto metody dělají následující: zkontrolují, zda už kurzor není na kraji menu a podle toho změní jeho souřadnice, poté změní index zvolené položky a zavolají metodu repaint(), která se postará o překreslení displeje. Při stisknutí tlačítka 2 je zavolána metoda proceed(). Ta zjistí, která položka menu je vybraná, a podle toho zavolá metodu třídy Abc.java. Jak sami vidíte, není to příliš složité, jediné, na co je třeba dávat pozor, je velikost displejů a volba použitých klávesových kódů. Pak už je jen na programátorovi, pro jakou metodu tvorby menu se při psaní midletu rozhodne.

V příkladu jsem použil podklad pro menu, který je vyhovující pro většinu dnes vyráběných mobilních telefonů. Následující obrázky ukazují, jak menu vypadá na různých mobilních telefonech:

Nokia 7210
Nokia 7210

Siemens S55
Siemens S55

Siemens SL45i
Siemens SL45i

Siemens M50
Siemens M50

Motorola i85s
Motorola i85s

V článku popsaný postup je jen malou ukázkou, kudy lze při tvorbě menu jít, možností je ale mnohem víc. Záleží jen na tvořivosti autora aplikace, jak si s tím poradí a kolik práce si s tvorbou menu dá. Nejvíce možností nabízejí samozřejmě barevné displeje, kterých je v nových mobilních telefonech čím dál víc, což vývojáři jen uvítají. Otevírají se tím další možnosti jak přiblížit kvalitu mobilních aplikací jejich „plnokrevným“ alternativám, které známe z PC.

Užitečné zdroje

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

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

1 Příspěvěk v diskuzi

  1. dobry den, mohl byste mi prosim vysvetlit nekdo tu metodu public void left()? nechapu jak to probiha.. :( diky moc

    public void left() {
    if(osa_x > 12) {
    osa_x = osa_x – 34;
    vyber = vyber – 1;
    repaint(); // vykresli podklad a kurzor na nove pozici
    } else {
    osa_x = 80;
    vyber = 3;
    repaint();
    }

Odpovědět