Creating a tip calculator on Kotlin: how does it work?

Original author: Lawrence Tan
  • Transfer

We’ll show you how to create a simple Kotlin tip calculator application. More specifically, Kotlin 1.3.21, Android 4, Android Studio 3. The article will be interesting, first of all, for those who begin their journey in the development of Android applications. It allows you to understand what and how it works inside the application.

Such a calculator is useful when you need to calculate the amount of tips from a company that decided to spend time in a restaurant or cafe. Of course, not all and not always left to waiters for tea, this is more of a Western tradition, but the development process of such an application is interesting in any case.

We remind you: for all readers of “Habr” - a discount of 10,000 rubles when registering for any Skillbox course using the “Habr” promo code.

Skillbox recommends: Practical course “Mobile Developer PRO .
Here's what the application looks like in the process of work:



You enter the desired percentage of the total amount, the number of participants in the meeting and get the result - the amount of tips that should be left.

Getting started


The full application interface is as follows:





The first action is to download the project basics . Open it in Android Studio 3.0 or later. We build and launch the project and see a white screen. Everything is fine, it should be so.





User actions are spelled out in the project in chronological order so that everything is clear. To view it, open View -> Tool Windows -> TODO.

We study the project and open colors.xml to evaluate the color palette. Text data (signatures) is placed in strings.xml, and there are several font templates in styles.xml.

Cost section development


Open activity_main.xml and add the code below in LinearLayout (# 1):


Now you can customize the values ​​directory style or play with colors using the material.io tool .

Now the project looks like this:


As you can see, the calculation of costs is carried out according to the data that the user makes.

Account Section Development


Add the code below in LinearLayout after the Expense Section (# 2):


Close LinearLayout after the list of TODOs, and then add a new code, placing it inside LinearLayout (# 3):


Since the main task of the application is to calculate the individual costs for each of the participants of gatherings in the restaurant, the main value is played by costPerPersonTextView.

EditText restricts input to one line; this parameter must have a NumberDecimal inputType value.


We start the project for the test and enter the parameters of the total damage (broken cups, plates, etc.)

Development of the section "People and Tips"


To add tip volume selection, insert the code below in the new LinearLayout section (# 4):


This section of code is necessary for accurate calculation of the tip amount. The default value of the text is 20. ImageButtons are provided with icons in the folder with write permissions.

We completely copy the section and add the following (# 5):

  • ImageButton ids (subtractPeopleButton, addPeopleButton)
  • TextView ids (numberOfPeopleStaticText, numberOfPeopleTextView)
  • DefaultText for numberOfPeopleTextView (must be 4).



Now when you start the application, it is possible to add the invoice amount, the "Add / Subtract" buttons also work, but so far nothing has happened.

Add Views


Open MainActivity.kt and add this to the initViews (# 6) function:

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
}

Finish the buttons


To add button click support, we implement the class-level View.OnClickListener (# 7):

class MainActivity : AppCompatActivity(), View.OnClickListener {

Compiling the project right now will not work, you need to perform a few more steps (# 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()
        }
    }

In terms of buttons and switches at Kotlin, everything is organized very cool! Add the code below to all the increment and decrement functions

(# 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()
        }
    }

Here, the code protects the increment functions with the maximum values ​​(MAX_TIP & MAX_PEOPLE). In addition, the code protects decrement functions with minimum values ​​(MIN_TIP & MIN_PEOPLE).

Now bind the buttons to the listeners in the initViews function (# 13):

private fun initViews() {
...
addTipButton.setOnClickListener(this)
        subtractTipButton.setOnClickListener(this)
addPeopleButton.setOnClickListener(this)
        subtractPeopleButton.setOnClickListener(this)
//TODO #15: Bind EditText to TextWatcher
}



Now you can add the total damage, tips and the number of participants in the meeting. Well, now the most important thing ...

Costing Section


This code calculates costs (# 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)
}

Well, here a function is called that makes it possible to take into account the number of people in the company and calculate the tip (# 15):

private fun incrementTip() {
…
}
private fun decrementTip() {
…
}
private fun incrementPeople() {
…
}
private fun decrementPeople() {
…
}

We launch the application. It looks and works fine. But it could be better.

If you try to delete the invoice amount, and then increase the number of tips or friends, the application will crash because there is no check for the zero cost yet. Moreover, if you try to change the invoice amount, the costs will not be updated.

Final steps


Add TextWatcher (# 16):

class MainActivity : AppCompatActivity(), View.OnClickListener, TextWatcher {

Then we embed the billEditText listener (# 17):

billEditText.addTextChangedListener(this)

Plus, add the code to execute 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) {}



Well, now absolutely everything works! Congratulations, you wrote your own Tipping Calculator on Kotlin.


Skillbox recommends:


Also popular now: