Lekce 6 - Android programování - Implementace Java kódu kalkulačky
V minulé lekci, Android programování - První aplikace, návrh kalkulačky, jsme se věnovali návrhu jednoduché kalkulačky.
V dnešní lekci si konečně ukážeme Java kód budoucí kalkulačky a dostaneme se tedy k programování!
Java kód aplikace
Kód budeme psát do souboru MainActivity.java
, který byl
vygenerován Android Studiem při vytváření projektu kalkulačky. Při
prvním pohledu do MainActivity.java
uvidíme tento kód,
obsahující jedinou metodu:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Zatím jediné dva řádky v onCreate()
volají metodu předka a
nastavují vzhled grafického uživatelského rozhraní odkazem na XML soubor
návrhu activity_main.xml
.
Nyní si ukážeme několik dalších částí kódu, které budeme do
MainActivity.java
postupně přidávat.
Deklarace proměnných
V souboru MainActivity.java
, nad metodou
onCreate()
, nejprve deklarujeme proměnné pro uložení referencí
na ty komponenty z XML návrhu, se kterými budeme pracovat v Java kódu:
EditText etNumber1; EditText etNumber2; Spinner spinnerOperation; Button btnCalculate; TextView labelResult;
Všimněte si, že chybí proměnná pro tlačítko =
. Jediná
práce s tlačítkem je nastavení obslužné metody při kliknutí. A protože
jsme toto udělali již v minulé části, přímo v XML návrhu tlačítka
parametrem android:onClick="calculate"
, nemusíme se o to již
starat v Java kódu. Lze říci, že jsme tím také ušetřili pár řádků
kódu, protože v Java kódu je tato činnost pracnější.
Metoda onCreate()
Metoda onCreate()
je tou nejdůležitější metodou naší
aplikace. Zde totiž, po spuštění aplikace, vše začíná.
Inicializace proměnných
Zde na konec doplníme inicializaci proměnných na potřebné komponenty z
XML návrhu. Díky tomu budeme moci s těmito objekty pracovat zde v Java kódu
(získávat obsah zadávacích políček, nastavovat text s výsledkem výpočtu
komponentě TextView
atd.):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etNumber1 = findViewById(R.id.etNumber1); etNumber2 = findViewById(R.id.etNumber2); spinnerOperation = findViewById(R.id.spinnerOperation); btnCalculate = findViewById(R.id.btnCalculate); labelResult = findViewById(R.id.labelResult); }
Jistě jste si všimli, že metoda onCreate()
přijímá jeden
parametr savedInstanceState
. Ten je po spuštění aplikace
null
. Slouží pro ukládání stavu aplikace a například po
změně orientace zařízení již null
nebude a bude obsahovat
některá data aplikace.
Položky pro Spinner
Na konec metody připíšeme další kód pro přípravu položek pro
Spinner
:
String[] operatorsArray = getResources().getStringArray(R.array.operators);
Vytváříme zde pole textových řetězců operatorsArray
se
čtyřmi operátory: ["+", "-", "*", "/"]
pro početní operace
kalkulačky, které budeme uživateli nabízet v rozbalovacím menu
Spinner
. Toto pole neinicializujeme přímo, ale hodnotami z pole
operators
, nacházejícího se v resources
v souboru
res/values/strings.xml
. Pojďme si tam hodnoty deklarovat.
strings.xml
Soubor strings.xml
byl při vytvoření projektu automaticky
vygenerován Android Studiem a my do něj přidáme deklaraci zmíněného pole
operators
:
<resources> <string name="app_name">SimpleCalc</string> <string-array name="operators"> <item>+</item> <item>-</item> <item>*</item> <item>/</item> </string-array> </resources>
První položka
<string name="app_name">SimpleCalc</string>
v souboru
strings.xml
byla automaticky vygenerována při vytvoření
projektu a obsahuje textový řetězec s názvem aplikace, který je zobrazován
například v toolbaru aplikace nebo v seznamu nainstalovaných aplikací v
uživatelově zařízení.
Všechny textové řetězce se v Android aplikacích píší do
strings.xml
, aby se aplikace dala jednoduše přeložit do více
jazyků. U znamének to zatím nedává smysl, ale co kdybychom tam přidali pak
nějakou další operaci, co by se jmenovala slovně.
Vrátíme se do metody onCreate()
a pokračujeme:
List list = new ArrayList(Arrays.asList(operatorsArray)); ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
Pole možností dosadíme do komponenty Spinner
pomocí
adaptéru. Pokud jste dělali formulářové aplikace v
Java Swing, je to podobné. Z vytvořeného pole operatorsArray
vytváříme kolekci List
, kterou předáme adaptéru pro
Spinner
, jehož úkolem je správa položek zobrazovaných
uživateli. Konstruktor adaptéru přijímá tři parametry:
- referenci na aktuální kontext
- referenci na XML návrh vzhledu té položky
Spinner
, která je aktuálně vybrána - kolekci s položkami
Spinner
Dalším řádkem spinneru nastavujeme vzhled položek zobrazených v jeho rozbalovacím menu:
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
I zde, podobně jako v případě vybrané položky, volíme defaultní vzhled položek menu.
V posledním řádku metody onCreate()
komponentě
Spinner
vytvořený adaptér přiřadíme:
spinnerOperation.setAdapter(dataAdapter);
Metoda calculate()
Nyní si popíšeme jedinou naší vlastní metodu, kterou přidáme do
souboru MainActivity.java
a která bude obsluhovat událost
kliknutí na tlačítko =
. Jak jsme si již řekli, tlačítko již
máme v XML na metodu napojené pomocí atributu
android:onClick="calculate"
.
Aby metoda calculate()
mohla na událost kliknutí reagovat,
musí přijímat parametr typu View
, který bude
obsahovat, při volání metody, referenci na ten objekt z XML, od kterého
událost přišla. Pokud tento parametr bude chybět, dojde po kliknutí na
tlačítko =
k pádu aplikace s chybou
IllegalStateException
:

Kód metody calculate()
máme zde:
public void calculate(View view) { double number1; double number2; double result = 0; try { number1 = Double.parseDouble(etNumber1.getText().toString()); number2 = Double.parseDouble(etNumber2.getText().toString()); if (spinnerOperation.getSelectedItem().equals("+")) { result = number1 + number2; } else if (spinnerOperation.getSelectedItem().equals("-")) { result = number1 - number2; } else if (spinnerOperation.getSelectedItem().equals("*")) { result = number1 * number2; } else if (spinnerOperation.getSelectedItem().equals("/")) { if (number2 == 0) { labelResult.setText("NULOU DĚLIT NELZE!"); return; } result = number1 / number2; } NumberFormat nf = new DecimalFormat("#.###"); labelResult.setText(nf.format(result)); } catch (NumberFormatException e) { labelResult.setText("Chybné zadání..."); } }
V úvodu metody calculate()
deklarujeme proměnné
number1
a number2
, do kterých budeme ukládat
uživatelem zadaná čísla a proměnnou result
pro uložení
výsledku výpočtu.
Další blok kódu je umístěn v bloku try
- catch
pro odchycení případné výjimky NumberFormatException
, ke
které dojde při zadání nečíselné hodnoty do jednoho z políček.
Konkrétně by k chybě došlo při převodu datových typů, kdy bude na
místě výsledku zobrazeno hlášení o chybném zadání. Do proměnných
number1
a number2
ukládáme obsah zadávacích
políček, který je pomocí třídy Double
převáděn z typu
String
na typ double
.
Po úspěšném převodu datových typů dochází podmínkou if
k větvení programu do čtyř možných scénářů podle typu matematické
operace, která je uživatelem vybrána ve Spinner
. Ve všech
případech do proměnné result
ukládáme výsledek výpočtu.
Pokud je požadovanou operací dělení, bude druhé zadané číslo otestováno
na nulovou hodnotu. Při nulové hodnotě druhého čísla by došlo k
porušení jedenáctého přikázání - dělení nulou . Pokud uživatel bude chtít
dělit nulou, vypíšeme mu, místo výsledku, hlášku o tom, že dělit nulou
nelze a metoda bude ukončena příkazem
return
.
Po provedení úspěšného výpočtu přichází čas k zobrazení
výsledku. Než výsledek zobrazíme v komponentě TextView
,
"proženeme" jej třídou NumberFormat
, která výsledek
zaokrouhlí na definovaný počet desetinných míst. Až po této úpravě
TextView
nastavujeme text v podobě získaného výsledku
výpočtu, aby byl zobrazen uživateli.
Kód kalkulačky tímto máme hotový
V následujícím kvízu, Kvíz - Úvod do Java Android základů, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.