Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Рассказываем, как создать простое приложение для расчета чаевых на языке Kotlin. Если точнее, то Kotlin 1.3.21, Android 4, Android Studio 3. Статья будет интересной, в первую очередь, для тех, кто начинает свой путь в разработке Android-приложений. Она позволяет понять, что и как работает внутри приложения.

Такой калькулятор пригодится, когда нужно подсчитать сумму чаевых с компании, решившей провести время в ресторане или кафе. Конечно, не все и не всегда оставляют официантам на чай, это больше западная традиция, но процесс разработки такого приложения в любом случае интересен.

Mir erënneren Iech: fir all Habr Lieser - eng Remise vun 10 Rubel wann Dir Iech an all Skillbox Cours aschreift mat dem Habr Promo Code.

Skillbox recommandéiert: Praktesch Cours «Мобильный разработчик PRO.

Вот как выглядит приложение в процессе работы:

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Вы вводите желаемый процент с общей суммы, количество участников встречи и получаете результат — сумму чаевых, которые стоит оставить.

Getting started

Полный интерфейс приложения выглядит следующим образом:
Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Первое действие — загрузка основы проекта. Открываем ее в Android Studio 3.0 или более поздней версии. Строим и запускаем проект и видим белый экран. Все нормально, так и должно быть.

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Действия пользователя прописаны в проекте в хронологическом порядке, чтобы все было понятно. Для его просмотра открываем View -> Tool Windows -> TODO.

Изучаем проект и открываем colors.xml для оценки цветовой палитры. В strings.xml размещены текстовые данные (подписи), а в styles.xml есть несколько шрифтовых шаблонов.

Разработка раздела затрат

Открываем activity_main.xml и добавляем расположенный ниже код в LinearLayout (#1):

<TextView
    android_id="@+id/expensePerPersonTextView"
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_paddingTop="30dp"
    style="@style/h1Bold"
    android_textColor="@color/colorAccent"
    android_text="0"/>
 
<TextView
    android_layout_width="match_parent"
    android_layout_height="wrap_content"
    android_paddingBottom="25dp"
    style="@style/h2"
    android_textColor="@color/colorAccent"
    android_text="@string/perPersonStaticText"/>

Теперь можно настроить стиль директории values или поиграть с цветами, используя инструмент material.io.

Сейчас проект выглядит так:

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?
Как видите, расчет затрат производится по данным, которые вносит пользователь.

Разработка раздела счетов

Добавляем код, размещенный ниже, в LinearLayout после Expense Section (#2):

<LinearLayout
    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_orientation="vertical"
    android_background="@color/colorAccent">
 
<! — TODO #3: Build Bill Section →
 
… 
</LinearLayout>

Закрываем LinearLayout после списка TODOs, а затем добавляем новый код, размещая его внутри LinearLayout (#3):

<TextView
      android_layout_margin="15dp"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      style="@style/h4"
      android_text="@string/billStaticText"/>
 
<EditText
      android_id="@+id/billEditText"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      android_inputType="numberDecimal"
      android_maxLines="1"
      style="@style/h2Bold"
      android_text="0"/>

Поскольку главная задача приложения — расчет индивидуальных затрат для каждого из участников посиделок в ресторане, то основное значение играет costPerPersonTextView.

EditText ограничивает ввод данных одной строкой, у этого параметра должно быть значение NumberDecimal inputType.

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?
Запускаем проект для теста и вводим параметры общего ущерба (разбитые чашки, тарелки и т.п.)

Разработка раздела «Люди и чаевые»

Чтобы добавить выбора объема чаевых, вставляем расположенный ниже код в новую секцию LinearLayout (#4):

<TextView
      android_layout_margin="15dp"
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_textColor="@color/colorWhite"
      style="@style/h4"
      android_text="@string/tipStaticText"/>
 
<LinearLayout
      android_layout_width="match_parent"
      android_layout_height="wrap_content"
      android_orientation="horizontal">
 
<ImageButton
        android_id="@+id/subtractTipButton"
        style="@style/operationButton"
        android_layout_marginLeft="20dp"
        android_layout_marginStart="20dp"
        android_src="@drawable/subtract"/>
 
<TextView
        android_id="@+id/tipTextView"
        android_layout_margin="15dp"
        android_layout_width="0dp"
        android_layout_height="wrap_content"
        android_textColor="@color/colorWhite"
        android_layout_weight="1"
        style="@style/h2Bold"
        android_text="20%"/>
 
<ImageButton
        android_id="@+id/addTipButton"
        style="@style/operationButton"
        android_layout_marginEnd="20dp"
        android_layout_marginRight="20dp"
        android_src="@drawable/add"/>
 
</LinearLayout>

Этот участок кода необходим для точного расчета суммы чаевых. Дефолтное значение текста — 20. ImageButtons снабжены иконками в папке с правами записи.

Полностью копируем раздел и добавляем следующее (#5):

  • ImageButton ids (subtractPeopleButton, addPeopleButton)
  • TextView ids (numberOfPeopleStaticText, numberOfPeopleTextView)
  • DefaultText для numberOfPeopleTextView (должен быть 4).

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Теперь при запуске приложения есть возможность добавить сумму счета, также работают кнопки «Добавить/Вычесть», но пока ничего не происходит.

Добавляем Views

Открываем MainActivity.kt и добавляем вот это в функцию 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
 
}

Доделываем кнопки

Чтобы добавить поддержку клика кнопок, внедряем View.OnClickListener на уровне класса (#7):

class MainActivity: AppCompatActivity(), View.OnClickListener {

Скомпилировать проект прямо сейчас не выйдет, нужно выполнить еще несколько действий (#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()
        }
    }

В плане кнопок и свитчей у Kotlin все организовано очень круто! Добавляем размещенный ниже код во все функции increment и 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()
        }
    }

Здесь код защищает функции приращения с максимальными значениями (MAX_TIP & MAX_PEOPLE). Кроме того, код защищает функции декремента с минимальными значениями (MIN_TIP & MIN_PEOPLE).

Теперь связываем кнопки со слушателями в функции initViews (#13):

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

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Теперь можно добавлять общий ущерб, чаевые и количество участников встречи. Ну и теперь самое главное…

Раздел подсчета затрат

Этот код подсчитывает затраты (#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)
 
}

Ну а здесь вызывается функция, которая дает возможность учесть количество людей в компании и подсчитать чаевые (#15):

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

Запускаем приложение. Выглядит и работает оно отлично. Но может быть и лучше.

Если вы попытаетесь удалить сумму счета, а затем увеличить число подсказок или друзей, приложение упадет, поскольку еще нет проверки для нулевого значения затрат. Более того, если вы попытаетесь изменить сумму счета, расходы не будут обновлены.

Finale Schrëtt

Добавляем TextWatcher (#16):

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

Затем встраиваем слушатель billEditText (#17):

billEditText.addTextChangedListener(this)

Плюс добавляем код для выполнения 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) {}

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Ну а теперь работает абсолютно все! Поздравляю, вы написали собственный «Калькулятор чаевых» на Kotlin.

Erstellt en Tipprechner zu Kotlin: wéi funktionnéiert et?

Skillbox recommandéiert:

Source: will.com

Setzt e Commentaire