
Popisujeme, jak vytvořit jednoduchou aplikaci pro výpočet spropitného v jazyce Kotlin. Konkrétně, Kotlin 1.3.21, Android 4, Android Studio 3. Tento článek bude zajímavý především pro ty, kteří začínají svou cestu ve vývoji aplikací pro Android. Umožňuje pochopit, co a jak funguje uvnitř aplikace.
Takový kalkulátor se hodí, když je potřeba spočítat částku spropitného pro skupinu, která se rozhodla strávit čas v restauraci nebo kavárně. Samozřejmě, ne všichni a ne vždy nechávají číšníkům spropitné, je to spíše západní tradice, ale proces vývoje takové aplikace je každopádně zajímavý.
Připomínáme: pro všechny čtenáře "Habra" – sleva 10 000 korun při registraci na jakýkoli kurz Skillbox s promokódem "Habr".
Skillbox doporučuje: Praktický kurz .
Takto aplikace vypadá během práce:

Zadáte požadovaný procentuální podíl z celkové částky, počet účastníků setkání a dostanete výsledek — částku spropitného, kterou byste měli nechat.
Začínáme
Celkový vzhled aplikace vypadá následovně:


První krok — . Otevřeme ji v Android Studio 3.0 nebo novější verzi. Sestavíme a spustíme projekt a vidíme bílou obrazovku. To je v pořádku, tak to má být.


Akce uživatele jsou v projektu napsány chronologicky, aby všechno dávalo smysl. Pro jejich zobrazení otevřeme View -> Tool Windows -> TODO.
Zkoumáme projekt a otevíráme colors.xml pro posouzení barevné palety. V strings.xml jsou umístěna textová data (popisky) a v styles.xml jsou některé šablony písem.
Vývoj sekce nákladů
Otevřeme activity_main.xml a přidáme níže uvedený kód do LinearLayout (#1):
Nyní můžete nastavit styl adresáře values nebo si hrát s barvami pomocí .
Teď projekt vypadá takto:

Jak vidíte, výpočet nákladů se provádí na základě údajů, které zadává uživatel.
Vývoj sekce účtů
Přidáváme níže uvedený kód do LinearLayout po Expense Section (#2):
<! — TODO #3: Vytvořit sekci účtů →
…Uzavíráme LinearLayout po seznamu úkolů a poté přidáváme nový kód, který umístíme do LinearLayout (#3):
Jelikož hlavním cílem aplikace je výpočet individuálních nákladů pro každého z účastníků večeře v restauraci, hraje klíčovou roli costPerPersonTextView.
EditText omezuje vstup na jeden řádek, tento parametr by měl mít hodnotu NumberDecimal inputType.

Spouštíme projekt pro testování a zadáváme parametry celkových škod (rozbité šálky, talíře atd.)
Vývoj sekce „Lidé a spropitné“
Abychom přidali možnost výběru výše spropitného, vložíme níže uvedený kód do nové sekce LinearLayout (#4):
Tento úsek kódu je nezbytný pro přesný výpočet částky spropitného. Výchozí hodnota textu je 20. ImageButtons jsou vybaveny ikonami v adresáři s právy pro zápis.
Úplně kopírujeme sekci a přidáme následující (#5):
- ImageButton ids (subtractPeopleButton, addPeopleButton)
- TextView ids (numberOfPeopleStaticText, numberOfPeopleTextView)
- DefaultText pro numberOfPeopleTextView (má být 4).

Nyní při spuštění aplikace existuje možnost přidat částku účtu, tlačítka „Přidat/Odebrat“ zatím fungují, ale zatím se neděje nic.
Přidáváme Views
Otevřete MainActivity.kt a přidejte toto do funkce initViews (#6):
private fun initViews() {
expensePerPersonTextView = findViewById(R.id.expensePerPersonTextView)
billEditText = findViewById(R.id.billEditText)
addTipButton = findViewById(R.id.addTipButton)
tipTextView = findViewById(R.id.tipTextView)
subtractTipButton = findViewById(R.id.subtractTipButton)
addPeopleButton = findViewById(R.id.addPeopleButton)
numberOfPeopleTextView = findViewById(R.id.numberOfPeopleTextView)
subtractPeopleButton = findViewById(R.id.subtractPeopleButton)
//TODO #8: Bind Buttons to Listener
//TODO #16: Bind EditText to TextWatcher
}Dokončujeme tlačítka
Chcete-li přidat podporu kliknutí tlačítek, implementujeme View.OnClickListener na úrovni třídy (#7):
class MainActivity: AppCompatActivity(), View.OnClickListener {
Teď není možné projekt zkompilovat, je třeba provést ještě několik kroků (#8):
override fun onClick(v: View?) {
when (v?.id) {
R.id.addTipButton -> incrementTip()
R.id.subtractTipButton -> decrementTip()
R.id.addPeopleButton -> incrementPeople()
R.id.subtractPeopleButton -> decrementPeople()
}
} Pokud jde o tlačítka a přepínače, je v Kotlinu vše skvěle organizováno! Přidáváme níže uvedený kód do všech funkcí increment a decrement
(#9–#12):
private fun incrementTip() {
if (tipPercent != MAX_TIP) {
tipPercent += TIP_INCREMENT_PERCENT
tipTextView.text = String.format("%d%%", tipPercent)
}
}
private fun decrementTip() {
if (tipPercent != MIN_TIP) {
tipPercent -= TIP_INCREMENT_PERCENT
tipTextView.text = String.format("%d%%", tipPercent)
}
}
private fun incrementPeople() {
if (numberOfPeople != MAX_PEOPLE) {
numberOfPeople += PEOPLE_INCREMENT_VALUE
numberOfPeopleTextView.text = numberOfPeople.toString()
}
}
private fun decrementPeople() {
if (numberOfPeople != MIN_PEOPLE) {
numberOfPeople -= PEOPLE_INCREMENT_VALUE
numberOfPeopleTextView.text = numberOfPeople.toString()
}
}Tento kód chrání funkce zvyšování s maximálními hodnotami (MAX_TIP & MAX_PEOPLE). Navíc kód chrání funkce snižování s minimálními hodnotami (MIN_TIP & MIN_PEOPLE).
Teď spojujeme tlačítka se listenery ve funkci initViews (#13):
private fun initViews() {
...
addTipButton.setOnClickListener(this)
subtractTipButton.setOnClickListener(this)
addPeopleButton.setOnClickListener(this)
subtractPeopleButton.setOnClickListener(this)
//TODO #15: Bind EditText to TextWatcher
} 
Teď můžeme přidávat celkovou škodu, spropitné a počet účastníků setkání. A teď to nejdůležitější…
Sekce výpočtu nákladů
Tento kód počítá náklady (#14):
private fun calculateExpense() {
val totalBill = billEditText.text.toString().toDouble()
val totalExpense = ((HUNDRED_PERCENT + tipPercent) / HUNDRED_PERCENT) * totalBill
val individualExpense = totalExpense / numberOfPeople
expensePerPersonTextView.text = String.format("$%.2f", individualExpense)
}A tady se volá funkce, která zohledňuje počet lidí ve společnosti a počítá spropitné (#15):
private fun incrementTip() {
…
}
private fun decrementTip() {
…
}
private fun incrementPeople() {
…
}
private fun decrementPeople() {
…
}Spouštíme aplikaci. Vypadá a funguje skvěle. Ale může to být ještě lepší.
Pokud se pokusíte odebrat částku účtu a poté zvýšit počet tipů nebo přátel, aplikace spadne, protože stále neexistuje kontrola pro nulovou hodnotu výdajů. Kromě toho, pokud se pokusíte změnit částku účtu, náklady nebudou aktualizovány.
Konečné kroky
Přidáváme TextWatcher (#16):
class MainActivity: AppCompatActivity(), View.OnClickListener, TextWatcher {
Poté vložíme listener billEditText (#17):
billEditText.addTextChangedListener(this)
Plus přidáme kód pro provádění TextWatcher (#18):
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (!billEditText.text.isEmpty()) {
calculateExpense()
}
}
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} 
A teď už všechno funguje perfektně! Gratuluji, napsali jste vlastní 'Kalkulačku spropitného' v Kotlinu.

Skillbox doporučuje:
- Dvouroční praktický kurz .
- Online kurz .
- Praktický roční kurz .
Zdroj: habr.com
