
We leggen uit hoe je een eenvoudige applicatie maakt voor het berekenen van fooien in de programmeertaal Kotlin. Om specifieker te zijn, het gaat om Kotlin 1.3.21, Android 4, Android Studio 3. Dit artikel is vooral interessant voor degenen die hun weg in de ontwikkeling van Android-applicaties beginnen. Het geeft inzicht in wat en hoe dingen binnen de applicatie werken.
Een dergelijke calculator is handig wanneer je de fooien wilt berekenen voor een groep die besloten heeft tijd door te brengen in een restaurant of café. Natuurlijk laten niet iedereen en niet altijd fooien voor de bediening, dit is meer een westerse traditie, maar het ontwikkelingsproces van zo'n applicatie is in ieder geval interessant.
Ter herinnering: voor alle lezers van «Habr» — een korting van 10.000 roebel bij inschrijving voor elke cursus van Skillbox met de promocode «Habr».
Skillbox raadt aan: Praktische cursus .
Zo ziet de applicatie eruit tijdens het gebruik:

Je voert het gewenste percentage van het totaalbedrag in, het aantal deelnemers aan de bijeenkomst en je krijgt het resultaat - het bedrag aan fooien dat je zou moeten achterlaten.
Laten we beginnen
De volledige interface van de applicatie ziet er als volgt uit:


De eerste stap is . We openen het in Android Studio 3.0 of een latere versie. We bouwen en starten het project en zien een wit scherm. Alles is in orde, dat is hoe het hoort.


De acties van de gebruiker zijn in het project in chronologische volgorde vastgelegd, zodat alles duidelijk is. Om dit te bekijken, openen we Weergave -> Hulpprogramma's -> TODO.
We bestuderen het project en openen colors.xml om de kleurenpalet te beoordelen. In strings.xml bevinden zich de tekstgegevens (labels), en in styles.xml zijn er enkele lettertype-sjablonen.
Ontwikkeling van de kostensectie
We openen activity_main.xml en voegen de onderstaande code toe aan LinearLayout (#1):
Nu kunnen we de stijl van de directory values aanpassen of met kleuren spelen, gebruikmakend van .
Op dit moment ziet het project er zo uit:

Zoals je kunt zien, worden de kosten berekend op basis van de gegevens die de gebruiker invoert.
Ontwikkeling van de rekeningensectie
Voeg de onderstaande code toe aan LinearLayout na de Expense Section (#2):
<! — TODO #3: Build Bill Section →
…Sluiten we de LinearLayout na de TODO-lijst, en voegen vervolgens nieuwe code toe door deze binnen de LinearLayout (#3) te plaatsen:
Aangezien de belangrijkste taak van de applicatie is om de individuele kosten voor elk van de deelnemers aan het diner te berekenen, speelt costPerPersonTextView een cruciale rol.
EditText beperkt de invoer tot één regel, deze parameter moet de waarde NumberDecimal inputType hebben.

Start het project voor een test en voer de parameters van de totale schade in (gebroken kopjes, borden, enz.)
Ontwikkeling van de sectie 'Mensen en fooien'
Om de selectie van het fooibedrag toe te voegen, plakken we de onderstaande code in een nieuwe sectie LinearLayout (#4):
Deze code is nodig voor de nauwkeurige berekening van het bedrag aan fooien. De standaardwaarde van de tekst is 20. ImageButtons zijn voorzien van pictogrammen in de map met schrijfrechten.
Kopieer de sectie volledig en voeg het volgende toe (#5):
- ImageButton ids (subtractPeopleButton, addPeopleButton)
- TextView ids (numberOfPeopleStaticText, numberOfPeopleTextView)
- DefaultText voor numberOfPeopleTextView (moet 4 zijn).

Nu, bij het starten van de applicatie, is het mogelijk om het bedrag van de rekening toe te voegen; de knoppen 'Toevoegen/Afhalen' werken ook, maar vooralsnog gebeurt er niets.
Voeg Views toe
Open MainActivity.kt en voeg dit toe aan de functie 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: Koppel knoppen aan listener
//TODO #16: Koppel EditText aan TextWatcher
}We werken de knoppen bij
Om klikondersteuning voor knoppen toe te voegen, implementeren we View.OnClickListener op klasseniveau (#7):
class MainActivity: AppCompatActivity(), View.OnClickListener {
Het project kan momenteel niet worden gecompileerd; er zijn nog enkele stappen nodig (#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()
}
} Wat betreft knoppen en schakelaars, is alles in Kotlin erg goed georganiseerd! Voeg de onderstaande code toe aan alle functie increment en 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()
}
}Hier beschermt de code de incrementeerfuncties met maximale waarden (MAX_TIP & MAX_PEOPLE). Daarnaast beschermt de code de decrementeerfuncties met minimale waarden (MIN_TIP & MIN_PEOPLE).
Laten we nu de knoppen koppelen aan de luisteraars in de functie initViews (#13):
private fun initViews() {
...
addTipButton.setOnClickListener(this)
subtractTipButton.setOnClickListener(this)
addPeopleButton.setOnClickListener(this)
subtractPeopleButton.setOnClickListener(this)
//TODO #15: Koppel EditText aan TextWatcher
} 
Nu kunnen we de totale schade, tips en het aantal deelnemers aan de bijeenkomst toevoegen. En nu het belangrijkste…
Sectie kostenberekening
Deze code berekent de kosten (#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)
}En hier wordt de functie aangeroepen die het mogelijk maakt om het aantal mensen in het bedrijf te overwegen en de tips te berekenen (#15):
private fun incrementTip() {
…
}
private fun decrementTip() {
…
}
private fun incrementPeople() {
…
}
private fun decrementPeople() {
…
}We starten de applicatie. Het ziet er goed uit en werkt uitstekend. Maar het kan beter.
Als je probeert het bedrag van de rekening te verwijderen en vervolgens het aantal tips of vrienden te verhogen, zal de applicatie crashen omdat er nog geen controle is op nulwaarden van kosten. Bovendien, als je probeert het bedrag van de rekening te wijzigen, worden de uitgaven niet bijgewerkt.
Laatste stappen
We voegen TextWatcher (#16) toe:
class MainActivity: AppCompatActivity(), View.OnClickListener, TextWatcher {
Daarna voegen we de listener voor billEditText in (#17) toe:
billEditText.addTextChangedListener(this)
Plus, we voegen code toe voor het uitvoeren van 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) {} 
En nu werkt alles perfect! Gefeliciteerd, je hebt je eigen 'Tip Calculator' in Kotlin geschreven.

Skillbox raadt aan:
- Praktische tweejarenopleiding .
- Online cursus .
- Praktische jaaropleiding .
Bron: habr.com
