Simple Calculator

This calculator allows users to perform basic arithmetic operations using a single EditText for input. It includes features like:

Simple Calculator Design

Handling number & operator input
Evaluating expressions
Clearing the input
Backspace functionality
Preventing additional input after displaying a result

Understanding the Components

  • EditText (edtInput): Used to display and input numbers/operators.
  • Buttons (onNumberClick): Handles number & operator inputs.
  • Equals Button (onCalculate): Evaluates the expression using ExpressionBuilder.
  • Clear Button (onClear): Clears all input.
  • Backspace Button (onBackspace): Removes the last character from the input.

Add the following dependency in the build.gradle file (Module : app)

implementation 'net.objecthunter:exp4j:0.4.8'

Java Code Explanation (MainActivity.java)

Handling Number Input

How It Works:

  1. Gets the clicked button’s text.
  2. If a result was displayed, clears the EditText.
  3. Adds the clicked number to the EditText.
public void onNumberClick(View view){
        Button button=(Button) view;
        String buttonText= button.getText().toString();
        if(isResultDisplayed){
            input.setText(""); // Clear input if a result was displayed
            isResultDisplayed=false;
        }
        input.append(buttonText);
 }

Evaluating the Expression (Equals Button)

How It Works:

  1. Extracts the input expression (e.g., 5+2*3).
  2. Evaluates the expression using ExpressionBuilder.
  3. Displays the calculated result.
  4. Sets isResultDisplayed = true to prevent additional input (ensuring users don’t modify results directly).
public void onCalculate(View view){
        String expression = input.getText().toString();
        try{
            Expression exp=new ExpressionBuilder(expression).build();
            double result=exp.evaluate();
            input.setText(String.valueOf(result));

            isResultDisplayed=true; // Set flag to prevent further input
        }
        catch (Exception e){
            input.setText("Error");
            isResultDisplayed=true; // Prevent input if an error occurs
        }
 }

Clearing the Input (C Button)

How It Works:

  • Completely clears the input field.
public void onClear(View view){
        input.setText(""); // Clear everything
        isResultDisplayed=false; // Allow fresh input
 }

Backspace Functionality (⌫ Button)

How It Works:

  1. If a result was displayed, clears everything.
  2. If input exists, removes the last character.
  3. Prevents deleting from an empty field.
public void onBackspace(View view){
        String currentText = input.getText().toString();

        if(isResultDisplayed){
            input.setText(""); // If result was displayed, clear everything
            isResultDisplayed = false;
            return;
        }
        if(!currentText.isEmpty()){
            input.setText(currentText.substring(0,currentText.length()-1));
        }
 }

XML Code for UI (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/txt_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:layout_marginTop="100dp"
        android:textSize="30dp"
        android:inputType="none" />

    <androidx.gridlayout.widget.GridLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:columnCount="4"
        app:rowCount="5"
        android:padding="10dp"
        android:layout_margin="20dp">

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="7" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="8" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="9" />

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:text="/"
            android:textSize="30dp" />

        <Button
            android:id="@+id/button5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="4" />

        <Button
            android:id="@+id/button6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="5" />

        <Button
            android:id="@+id/button7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="6" />

        <Button
            android:id="@+id/button8"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="*" />

        <Button
            android:id="@+id/button9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="1" />

        <Button
            android:id="@+id/button10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="2" />

        <Button
            android:id="@+id/button11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="3" />

        <Button
            android:id="@+id/button12"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:text="-"
            android:textSize="30dp" />

        <Button
            android:id="@+id/button13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="0" />

        <Button
            android:id="@+id/button14"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClear"
            android:textSize="30dp"
            android:text="c" />

        <Button
            android:id="@+id/button15"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onCalculate"
            android:textSize="30dp"
            android:text="=" />

        <Button
            android:id="@+id/button16"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="+" />

        <Button
            android:id="@+id/button19"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNumberClick"
            android:textSize="30dp"
            android:text="." />

        <Button
            android:id="@+id/button20"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="30dp"
            android:onClick="onBackspace"
            android:text="BS" />
    </androidx.gridlayout.widget.GridLayout>
</LinearLayout>

Complete Java code

package com.example.part_b3_simple_calculator_2024;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import net.objecthunter.exp4j.Expression;
import net.objecthunter.exp4j.ExpressionBuilder;

public class MainActivity extends AppCompatActivity {

    private EditText input;
    private boolean isResultDisplayed=false; // Flag to track if result is displayed

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        input=findViewById(R.id.txt_input);
    }
    public void onNumberClick(View view){
        Button button=(Button) view;
        String buttonText= button.getText().toString();
        if(isResultDisplayed){
            input.setText(""); // Clear input if a result was displayed
            isResultDisplayed=false;
        }
        input.append(buttonText);
    }
  
    public void onClear(View view){
        input.setText(""); // Clear everything
        isResultDisplayed=false; // Allow fresh input
    }

    // Function to handle equals button
    public void onCalculate(View view){
        String expression = input.getText().toString();
        try{
            Expression exp=new ExpressionBuilder(expression).build();
            double result=exp.evaluate();
            input.setText(String.valueOf(result));

            isResultDisplayed=true; // Set flag to prevent further input
        }
        catch (Exception e){
            input.setText("Error");
            isResultDisplayed=true; // Prevent input if an error occurs
        }
    }
    public void onBackspace(View view){
        String currentText = input.getText().toString();

        if(isResultDisplayed){
            input.setText(""); // If result was displayed, clear everything
            isResultDisplayed = false;
            return;
        }
        if(!currentText.isEmpty()){
            input.setText(currentText.substring(0,currentText.length()-1));
        }
    }
}