KOTLIN

How to Create Simple Calculator in Android Studio Kotlin

How to Create Simple Calculator in Android Studio

In this Tutorial we will learn how to create a simple calculator in android studio.Lets start

How to Create Simple Calculator in Android Studio Kotlin

Step 1: Building the user interface

First we design our user interface using TextView, Button and ImageButton. TextView are used to display user input and result, Button and ImageButton are Used to get user Input.

<?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:padding="15dp"
    android:weightSum="3"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1">
        <TextView
            android:id="@+id/display"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:padding="5dp"
            android:gravity="end|bottom"
            android:hint="0"
            android:textSize="36dp"
            android:fontFamily="sans-serif-black"
            android:maxLines="4"
            android:textColor="@android:color/black"
            android:background="@android:color/transparent" />
        <TextView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:visibility="gone"
            android:layout_weight=".5"
            android:padding="5dp"
            android:gravity="end|bottom"
            android:text="="
            android:textSize="26dp"
            android:fontFamily="sans-serif-black"
            android:maxLines="4"
            android:textColor="@android:color/black"
            android:background="@android:color/transparent" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="@android:color/black"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:weightSum="5"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:weightSum="4">
            <Button
                android:id="@+id/button_clear"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="C"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
            <Button
                android:id="@+id/button_modulas"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="%"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
            <Button
                android:id="@+id/button_div"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="÷"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
            <Button
                android:id="@+id/button_multi"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="×"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:weightSum="4">
            <Button
                android:id="@+id/button_7"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="7"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_8"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="8"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_9"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="9"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_sub"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="-"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            android:weightSum="4">
            <Button
                android:id="@+id/button_4"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="4"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_5"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="5"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_6"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="6"
                android:textSize="26dp"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_btn"/>
            <Button
                android:id="@+id/button_add"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:text="+"
                android:textSize="26dp"
                android:textColor="@color/colorAccent"
                android:fontFamily="sans-serif-black"
                android:background="@drawable/ripple_bg"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:orientation="horizontal"
            android:weightSum="4">
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:layout_weight="3"
                android:weightSum="2">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:orientation="horizontal"
                    android:weightSum="3">
                    <Button
                        android:id="@+id/button_3"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:text="3"
                        android:textSize="26dp"
                        android:fontFamily="sans-serif-black"
                        android:background="@drawable/ripple_btn"/>
                    <Button
                        android:id="@+id/button_2"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:text="2"
                        android:textSize="26dp"
                        android:fontFamily="sans-serif-black"
                        android:background="@drawable/ripple_btn"/>
                    <Button
                        android:id="@+id/button_1"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:text="1"
                        android:textSize="26dp"
                        android:fontFamily="sans-serif-black"
                        android:background="@drawable/ripple_btn"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="1"
                    android:orientation="horizontal"
                    android:weightSum="3">
                    <ImageButton
                        android:id="@+id/button_back"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:src="@drawable/back"
                        android:backgroundTint="@color/colorAccent"
                        android:background="@drawable/ripple_bg"/>
                    <Button
                        android:id="@+id/button_0"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:text="0"
                        android:textSize="26dp"
                        android:fontFamily="sans-serif-black"
                        android:background="@drawable/ripple_btn"/>
                    <Button
                        android:id="@+id/button_dot"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_weight="1"
                        android:text="."
                        android:textSize="26dp"
                        android:fontFamily="sans-serif-black"
                        android:background="@drawable/ripple_btn"/>
                </LinearLayout>
            </LinearLayout>
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1">
                <Button
                    android:id="@+id/button_equal"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:text="="
                    android:textSize="40dp"
                    android:textColor="@android:color/white"
                    android:fontFamily="sans-serif-black"
                    android:background="@drawable/ripple_equal_btn"/>
            </LinearLayout>
        </LinearLayout>        
    </LinearLayout>
</LinearLayout>

Step 2: Setup Resource file

1. Right click on drawable -> new -> Image Asset Choose Icon Type Action Bar and Tab Icons then click Click Art Image and select Which Icon Name is close then press ok and then name it back and change color and use this color code D81B60 finaly click next->Finish.

2. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_bg.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_bg.xml.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorPrimaryDark"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="0dp" />
        </shape>
    </item>
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@android:color/transparent"
                android:startColor="@android:color/transparent"
                android:type="linear" />
            <corners android:radius="0dp" />
        </shape>
    </item>
</ripple>

3. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_btn.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_btn.xml.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#88000000"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#88000000" />
            <corners android:radius="0dp" />
        </shape>
    </item>
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@android:color/transparent"
                android:startColor="@android:color/transparent"
                android:type="linear" />
            <corners android:radius="0dp" />
        </shape>
    </item>
</ripple>

4. Right click on drawable -> new -> Drawable Resource File then name it ripple_bg and click Ok. You can see ripple_equal_btn.xml file under your drawable folder. Copy the bellow code and paste it into your ripple_equal_btn.xml.

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#000000"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#000000" />
            <corners android:radius="0dp" />
        </shape>
    </item>
    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryDark"
                android:startColor="@color/colorPrimaryDark"
                android:type="linear" />
            <corners android:radius="0dp" />
        </shape>
    </item>
</ripple>

Now your design look like this

Step 3: Coding the Functionality

In your Java file, which is almost always MainActivity.java by default, head on over to the MainActivity extends AppCompatActivity class. Copy bellow code and paste into your MainActivity.kt file. But without changing your project package name [ package com.andrious.simplecalculator; ]

import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
import android.view.View
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    var result_value: Double = 0.0
    var checker:Boolean = true
    var orientation = 0
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var button_0  = findViewById(R.id.button_0) as Button
        var button_1  = findViewById(R.id.button_1) as Button
        var button_2  = findViewById(R.id.button_2) as Button
        var button_3  = findViewById(R.id.button_3) as Button
        var button_4  = findViewById(R.id.button_4) as Button
        var button_5  = findViewById(R.id.button_5) as Button
        var button_6  = findViewById(R.id.button_6) as Button
        var button_7  = findViewById(R.id.button_7) as Button
        var button_8  = findViewById(R.id.button_8) as Button
        var button_9  = findViewById(R.id.button_9) as Button
        var button_add  = findViewById(R.id.button_add) as Button
        var button_sub  = findViewById(R.id.button_sub) as Button
        var button_multi  = findViewById(R.id.button_multi) as Button
        var button_div  = findViewById(R.id.button_div) as Button
        var button_modulas  = findViewById(R.id.button_modulas) as Button
        var button_dot  = findViewById(R.id.button_dot) as Button
        var button_equal  = findViewById(R.id.button_equal) as Button
        var button_clear  = findViewById(R.id.button_clear) as Button
        var button_back  = findViewById(R.id.button_back) as ImageButton
        var result  = findViewById(R.id.result) as TextView
        var display  = findViewById(R.id.display) as TextView
        
        orientation = resources.configuration.orientation
        button_modulas.isEnabled = false
        entry_controller(checker)

        button_0.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "0"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })
        button_1.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "1"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })
        button_2.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "2"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })
        button_3.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "3"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })
        button_4.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "4"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })
        button_5.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "5"
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_6.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "6"
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_7.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "7"
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_8.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "8"
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_9.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "9"
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_dot.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "."
            text_size_color_controller()
            checker = false
            entry_controller(checker)
        })
        button_add.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "+"
            text_size_color_controller()
            checker = true
            entry_controller(checker)
        })
        button_sub.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "-"
            text_size_color_controller()
            checker = true
            entry_controller(checker)
        })
        button_multi.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "*"
            text_size_color_controller()
            checker = true
            entry_controller(checker)
        })
        button_div.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "/"
            text_size_color_controller()
            checker = true
            entry_controller(checker)
        })
        button_modulas.setOnClickListener(View.OnClickListener {

            result.text = "=" + (result_value/100.0).toString()
        })
        button_clear.setOnClickListener(View.OnClickListener {
            display.text = ""
            result.text = ""
            result.visibility = View.GONE
            display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
        })
        button_back.setOnClickListener(View.OnClickListener {
            var data = display.text.toString()
            if(data.length > 0){
                display.text = data.substring(0, data.length - 1)
                text_size_color_controller();
            }
        })
        button_equal.setOnClickListener(View.OnClickListener {
            var data = display.text.toString()
            if(!data.endsWith("+") || !data.endsWith("-") || !data.endsWith("*") || !data.endsWith("/")){
                result_value = calculation(data)
                result.visibility = View.VISIBLE
                result.text = "= " + String.format("%.5f", result_value).toDouble().toString()
                display.setTextColor(Color.parseColor("#bdbdbd"))
                result.setTextColor(Color.parseColor("#000000"))
                if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    // In landscape
                    display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
                    result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
                } else {
                    // In portrait
                    display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
                    result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
                }
                button_modulas.isEnabled = true
            }
        })
    }
    fun text_size_color_controller(): Void? {
        display.setTextColor(Color.parseColor("#000000"))
        result.setTextColor(Color.parseColor("#bdbdbd"))
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // In landscape
            display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,30F)
            result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
        } else {
            // In portrait
            display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
            result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
        }
        button_modulas.isEnabled = false

        return null
    }

    fun entry_controller(b:Boolean): Void? {
        if(b){
            button_add.isEnabled = false
            button_sub.isEnabled = false
            button_multi.isEnabled = false
            button_div.isEnabled = false
            button_equal.isEnabled = false
        }else{
            button_add.isEnabled = true
            button_sub.isEnabled = true
            button_multi.isEnabled = true
            button_div.isEnabled = true
            button_equal.isEnabled = true
        }
        return null
    }
    fun calculation(str: String): Double {
        return object : Any() {
            var pos = -1
            var ch = 0
            fun nextChar() {
                if(++pos < str.length){
                    ch = str[pos].toInt()
                }else{
                    ch = -1
                }
            }
            fun eat(charToEat: Int): Boolean {
                while (ch == ' '.toInt()) nextChar()
                if (ch == charToEat) {
                    nextChar()
                    return true
                }
                return false
            }
            fun parse(): Double {
                nextChar()
                val x = parseExpression()
                if (pos < str.length) throw RuntimeException("Unexpected: " + ch.toChar())
                return x
            }

            // Grammar:
            // expression = term | expression `+` term | expression `-` term
            // term = factor | term `*` factor | term `/` factor
            // factor = `+` factor | `-` factor | `(` expression `)`
            //        | number | functionName factor | factor `^` factor
            fun parseExpression(): Double {
                var x = parseTerm()
                while (true) {
                    if (eat('+'.toInt())) x += parseTerm() // addition
                    else if (eat('-'.toInt())) x -= parseTerm() // subtraction
                    else return x
                }
            }

            fun parseTerm(): Double {
                var x = parseFactor()
                while (true) {
                    if (eat('*'.toInt())) x *= parseFactor() // multiplication
                    else if (eat('/'.toInt())) x /= parseFactor() // division
                    else return x
                }
            }

            fun parseFactor(): Double {
                if (eat('+'.toInt())) return parseFactor() // unary plus
                if (eat('-'.toInt())) return -parseFactor() // unary minus
                var x: Double
                val startPos = pos
                if (eat('('.toInt())) { // parentheses
                    x = parseExpression()
                    eat(')'.toInt())
                } else if (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) { // numbers
                    while (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) nextChar()
                    x = str.substring(startPos, pos).toDouble()
                } else if (ch >= 'a'.toInt() && ch <= 'z'.toInt()) { // functions
                    while (ch >= 'a'.toInt() && ch <= 'z'.toInt()) nextChar()
                    val func = str.substring(startPos, pos)
                    x = parseFactor()
                    x =
                        if (func == "sqrt") Math.sqrt(x) else if (func == "sin") Math.sin(
                            Math.toRadians(
                                x
                            )
                        ) else if (func == "cos") Math.cos(Math.toRadians(x)) else if (func == "tan") Math.tan(
                            Math.toRadians(x)
                        ) else throw RuntimeException(
                            "Unknown function: $func"
                        )
                } else {
                    throw RuntimeException("Unexpected: " + ch.toChar())
                }
                if (eat('^'.toInt())) x = Math.pow(x, parseFactor()) // exponentiation
                return x
            }
        }.parse()
    }
}

Now every thing is done. Run and enjoy the calculator app.

Step 4: Function description

Fetching values from the elements into the working of our app

Inside the onCreate function, we will fetch all values and assign them to our objects. We do this by the following code

var button_0  = findViewById(R.id.button_0) as Button

Here, we are fetching the value of ‘button_0’, which is the ID of our button zero, and storing it in the object ‘button_0’ that we created earlier. Though they are named the same, Android Studio can identify the correct one. But if it gets confusing for you, feel free to give either one of them any other names.

We do the same with our TextView.

var display  = findViewById(R.id.display) as TextView

Changing the TextView value by pressing the buttons.

button_0.setOnClickListener(View.OnClickListener {
            display.text = display.text.toString() + "0"
            text_size_color_controller();
            checker = false
            entry_controller(checker)
        })

We use OnClickListener for this part of the program. This is what happens when you push zero. The TextView, first already fetches the value that it is already displaying, null in this case, and then adds 0 to it.

Text Font size control when change the phone orientation.

First declare a global variable

var orientation = 0

In onCreate method we initialize it and get the device current orientation.

orientation = resources.configuration.orientation

Finally use conditional statement in button_equal onClick function based on device orientation.

if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    // In landscape
                    display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
                    result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
                } else {
                    // In portrait
                    display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
                    result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
                }

Text size and color control function

fun text_size_color_controller(): Void? {
        display.setTextColor(Color.parseColor("#000000"))
        result.setTextColor(Color.parseColor("#bdbdbd"))
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // In landscape
            display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,30F)
            result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,20F)
        } else {
            // In portrait
            display.setTextSize(TypedValue.COMPLEX_UNIT_DIP,36F)
            result.setTextSize(TypedValue.COMPLEX_UNIT_DIP,26F)
        }
        button_modulas.isEnabled = false
        return null
    }

This function control text size and color when equal button click. This function also check the device orientation for controlling the text size.

User Entry Control Function

fun entry_controller(b:Boolean): Void? {
        if(b){
            button_add.isEnabled = false
            button_sub.isEnabled = false
            button_multi.isEnabled = false
            button_div.isEnabled = false
            button_equal.isEnabled = false
        }else{
            button_add.isEnabled = true
            button_sub.isEnabled = true
            button_multi.isEnabled = true
            button_div.isEnabled = true
            button_equal.isEnabled = true
        }
        return null
    }

This function work like this if user don’t write any number but click addition or subtraction button, this function handle this type of error. If user don’t type any number then all the operation button are disabled. Other exception is if user write like this 2+2+ and press enter then app will be crashed. This function also handle this. If user input last value is any operator then equal button automatically disabled. It also handle if user click any operator button then all the operator buttons are automatically disabled. If user need to change the operator click the back button then automatically enable all the operator buttons.

Calculation Function

fun calculation(str: String): Double {
        return object : Any() {
            var pos = -1
            var ch = 0
            fun nextChar() {
                if(++pos < str.length){
                    ch = str[pos].toInt()
                }else{
                    ch = -1
                }
            }
            fun eat(charToEat: Int): Boolean {
                while (ch == ' '.toInt()) nextChar()
                if (ch == charToEat) {
                    nextChar()
                    return true
                }
                return false
            }
            fun parse(): Double {
                nextChar()
                val x = parseExpression()
                if (pos < str.length) throw RuntimeException("Unexpected: " + ch.toChar())
                return x
            }

            // Grammar:
            // expression = term | expression `+` term | expression `-` term
            // term = factor | term `*` factor | term `/` factor
            // factor = `+` factor | `-` factor | `(` expression `)`
            //        | number | functionName factor | factor `^` factor
            fun parseExpression(): Double {
                var x = parseTerm()
                while (true) {
                    if (eat('+'.toInt())) x += parseTerm() // addition
                    else if (eat('-'.toInt())) x -= parseTerm() // subtraction
                    else return x
                }
            }

            fun parseTerm(): Double {
                var x = parseFactor()
                while (true) {
                    if (eat('*'.toInt())) x *= parseFactor() // multiplication
                    else if (eat('/'.toInt())) x /= parseFactor() // division
                    else return x
                }
            }

            fun parseFactor(): Double {
                if (eat('+'.toInt())) return parseFactor() // unary plus
                if (eat('-'.toInt())) return -parseFactor() // unary minus
                var x: Double
                val startPos = pos
                if (eat('('.toInt())) { // parentheses
                    x = parseExpression()
                    eat(')'.toInt())
                } else if (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) { // numbers
                    while (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) nextChar()
                    x = str.substring(startPos, pos).toDouble()
                } else if (ch >= 'a'.toInt() && ch <= 'z'.toInt()) { // functions
                    while (ch >= 'a'.toInt() && ch <= 'z'.toInt()) nextChar()
                    val func = str.substring(startPos, pos)
                    x = parseFactor()
                    x =
                        if (func == "sqrt") Math.sqrt(x) else if (func == "sin") Math.sin(
                            Math.toRadians(
                                x
                            )
                        ) else if (func == "cos") Math.cos(Math.toRadians(x)) else if (func == "tan") Math.tan(
                            Math.toRadians(x)
                        ) else throw RuntimeException(
                            "Unknown function: $func"
                        )
                } else {
                    throw RuntimeException("Unexpected: " + ch.toChar())
                }
                if (eat('^'.toInt())) x = Math.pow(x, parseFactor()) // exponentiation
                return x
            }
        }.parse()
    }

When user click equal button then equal button onClickListener function get the all user input as string then pass it int this calculation function. This function phrase the string and calculate the value and return result as decimal data type.

About Israfil Mahmud Raju

I am Israfil Mahmud Raju. My Passion is Android App Developing. This site is a way for me to showcase all of my works, projects in one location.
View all posts by Israfil Mahmud Raju →