Создание собственного калькулятора — это обряд посвящения для каждого начинающего Android-разработчика. В этом руководстве вы узнаете, как сделать калькулятор в андроид студио, используя современный Kotlin и два популярных подхода к построению интерфейса: классический XML на основе LinearLayout и декларативный Jetpack Compose. Мы не только напишем работающее приложение, но и разберем архитектурные решения, которые позволят вам расширять его функциональность без боли.
Инструментарий и подготовка проекта
Для работы потребуется актуальная версия Android Studio. Создайте новый проект с пустой активностью (Empty Views Activity или Empty Compose Activity). Второй вариант предпочтительнее для Jetpack Compose, но если вы выбираете XML, достаточно шаблона с Empty Views. Обязательно выберите Kotlin в качестве основного языка и убедитесь, что минимальный SDK не ниже 24, чтобы использовать все современные API.
Для вычислений мы воспользуемся библиотекой exp4j, которая умеет разбирать математические выражения в строковом виде и соблюдает порядок операций. Это избавляет от написания собственного парсера. Добавьте зависимость в build.gradle.kts модуля app:
dependencies {
implementation("net.objecthunter:exp4j:0.4.8")
}
Дизайн интерфейса: XML против Jetpack Compose
Прежде чем погружаться в код, стоит сравнить оба подхода, поскольку вопрос как сделать калькулятор в андроид студио часто подразумевает выбор между классической версткой и современным тулкитом. В таблице ниже приведены ключевые отличия.
| Критерий | XML (LinearLayout) | Jetpack Compose |
|---|---|---|
| Язык разметки | Отдельные XML-файлы в res/layout | Код на Kotlin внутри @Composable функций |
| Сложность освоения | Низкая, много готовых примеров | Средняя, требует понимания реактивности |
| Производительность | Может страдать при глубокой вложенности | Оптимальна за счет перекомпоновки только изменившихся элементов |
| Обновление UI | Ручное через findViewById или ViewBinding | Автоматическое через состояние (mutableStateOf) |
Вариант 1: Верстка на LinearLayout
Макет калькулятора состоит из двух частей: дисплей для ввода выражения и результата, а также панель кнопок. Корневым контейнером выступает вертикальный LinearLayout с черным фоном. Верхняя половина экрана отводится под два TextView: operation (выражение) и result (ответ). Нижняя половина — пять горизонтальных LinearLayout, каждый из которых содержит по пять кнопок с равным весом.
Кнопки стилизуются через themes.xml, чтобы избежать дублирования кода. Создайте три стиля: Numbers (белый текст на сером фоне для цифр), Operations (оранжевый текст для базовых операций) и Operations_Sci (светло-серый текст для дополнительных функций). Каждая кнопка получает уникальный id, например, b_1, b_2, b_add, b_eq.
Пример фрагмента разметки для первого ряда кнопок:
<LinearLayout
android:orientation="horizontal"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView android:text="C" android:id="@+id/b_clear" style="@style/Operations" />
<TextView android:text="(" android:id="@+id/b_leftb" style="@style/Operations_Sci" />
<TextView android:text=")" android:id="@+id/b_rightb" style="@style/Operations_Sci" />
<TextView android:text="/" android:id="@+id/b_div" style="@style/Operations" />
<TextView android:text="*" android:id="@+id/b_mul" style="@style/Operations" />
</LinearLayout>
Логика калькулятора на Kotlin с exp4j
Вся магия происходит в MainActivity.kt. После привязки элементов интерфейса через ViewBinding или findViewById, для каждой кнопки-цифры и операции устанавливается слушатель, который добавляет соответствующий символ в TextView operation. Кнопка back удаляет последний символ, а clear очищает оба поля.
Сердце вычислений — обработчик кнопки «равно». Он извлекает строку выражения, передает её в ExpressionBuilder из библиотеки exp4j, а затем вызывает evaluate(). Если выражение составлено корректно, ответ форматируется: целые числа отображаются без десятичной точки, дробные — с сохранением знаков после запятой. В случае ошибки в поле result выводится "Error". Вот основной фрагмент кода:
b_eq.setOnClickListener {
val optext = operation.text.toString()
if (optext.isNotEmpty()) {
try {
val expr = ExpressionBuilder(optext).build()
val res = expr.evaluate()
val longres = res.toLong()
result.text = if (longres.toDouble() == res) longres.toString() else res.toString()
} catch (e: Exception) {
result.text = "Error"
}
}
}
Такой подход позволяет обрабатывать сложные выражения со скобками и приоритетами операций, не реализуя алгоритм сортировочной станции вручную.
Вариант 2: Реализация на Jetpack Compose
Если вы предпочитаете декларативный UI, как сделать калькулятор в андроид студио с помощью Compose — задача, решаемая еще лаконичнее. Вся верстка описывается непосредственно в Kotlin-функциях, а состояние управляется через remember и mutableStateOf. Кнопки размещаются в Column и Row с равным весом, что достигается модификатором Modifier.weight(1f).
Преимущества Compose проявляются в реактивности: при изменении строки выражения интерфейс обновляется автоматически, без вызова invalidate. Пример компонента кнопки:
@Composable
fun CalculatorButton(symbol: String, onClick: () -> Unit) {
Button(
onClick = onClick,
modifier = Modifier.weight(1f).padding(2.dp)
) {
Text(symbol, fontSize = 20.sp)
}
}
Логика вычислений остается той же — вызов exp4j через ExpressionBuilder, но теперь строка выражения хранится в состоянии var expression by remember { mutableStateOf("") }, а результат — в var result by remember { mutableStateOf("") }.
Тестирование и сборка APK
Когда приложение готово, запустите его на эмуляторе или реальном устройстве. Проверьте базовые операции: сложение, вычитание, умножение, деление, а также сценарии с ошибками (деление на ноль, несбалансированные скобки). Убедитесь, что кнопка back корректно удаляет последний символ, а результат можно перенести в поле выражения для продолжения расчетов.
Для распространения приложения создайте APK через пункт меню Build → Build Bundle(s) / APK(s) → Build APK(s). Готовый файл будет находиться в папке app/build/outputs/apk/debug/.
Типичные ошибки и их решение
- Приложение крашится при нажатии на кнопку. Проверьте, что все id в findViewById или ViewBinding совпадают с указанными в XML. Если используется Compose, убедитесь, что onClick-обработчики переданы корректно.
- Выражение "2+2*2" дает 8 вместо 6. Это означает, что вы не используете библиотеку вроде exp4j, а пытаетесь вычислять операции линейно. Подключите ExpressionBuilder, который учитывает математический приоритет.
- Кнопки растянуты неравномерно. При использовании LinearLayout задайте ширину каждой кнопки 0dp и вес 1. В Compose примените Modifier.weight(1f) внутри Row или Column.
- Ошибка компиляции "cannot resolve symbol exp4j". Убедитесь, что зависимость добавлена в build.gradle.kts модуля app и выполнен Gradle Sync.
Итоги
Вы узнали, как сделать калькулятор в андроид студио двумя способами: через классический XML с LinearLayout и через современный Jetpack Compose. Оба подхода опираются на библиотеку exp4j для безопасного вычисления выражений. Этот проект закрывает базовые потребности начинающего разработчика: верстка интерфейса, обработка пользовательского ввода, подключение сторонних библиотек и сборка APK. Дальнейшие улучшения — добавление памяти, истории операций или научных функций — станут отличной практикой для закрепления навыков. Сохраните этот урок в закладки и используйте как шпаргалку при создании собственных приложений.