Skip to main content

Simple Calculator With ViewModel and LIveData



This is a simple calculator with basic mathematical operations.
You can download full source code of this project from Github
https://github.com/arunkfedex/SimpleCalculator 
We are using ViewModel and LiveData so we need to add those dependencies in build.gradle file.

build.gradle
plugins {
    id 'com.android.application'
    id 'kotlin-android'
}
android {
    compileSdk 30
    defaultConfig {
        applicationId "com.arun.androidtutsforu.simplecalculator"
        minSdk 21
        targetSdk 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures{
        dataBinding true
    }
}
dependencies {
    def lifecycle_version = "2.4.0-alpha03"
    implementation 'androidx.core:core-ktx:1.6.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    implementation "androidx.fragment:fragment-ktx:1.3.6"
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

}
Next is our layout file activity_main.xml 
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">
<fragment
    android:id="@+id/simpleCalcFragment"
    android:name="com.arun.androidtutsforu.simplecalculator.calculator.SimpleCalcFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>                 
                         
our activity_main.xml file is just holding our fragment , which contains all the ui elements 
fragment_simple_calc.xml
                         
 <?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
     <variable
         name="simpleCalcViewModel"
         type="com.arun.androidtutsforu.simplecalculator.calculator.SimpleCalcViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".calculator.SimpleCalcFragment">
        <TextView
            android:id="@+id/number"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:text="@{simpleCalcViewModel.number}"
            android:textAlignment="viewEnd"
            android:textColor="@color/black"
            android:textSize="35sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <TextView
            android:id="@+id/result"
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:text="@{simpleCalcViewModel.result}"
            android:textAlignment="viewEnd"
            android:textColor="@color/black"
            android:textSize="45sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/number" />

        <Button
            android:id="@+id/zero"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`0`)}"
            android:text="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/dot"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />
        <Button
            android:id="@+id/dot"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`.`)}"
            android:text="."
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/equal"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/zero" />
        <Button
            android:id="@+id/equal"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.equalToClicked()}"
            android:text="="
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/plus"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/dot" />
        <Button
            android:id="@+id/plus"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.operatorClicked(`+`)}"
            android:text="+"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/equal" />
        <Button
            android:id="@+id/one"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`1`)}"
            android:text="1"
            app:layout_constraintBottom_toTopOf="@+id/zero"
            app:layout_constraintEnd_toStartOf="@+id/two"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />
        <Button
            android:id="@+id/two"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`2`)}"
            android:text="2"
            app:layout_constraintBottom_toTopOf="@+id/dot"
            app:layout_constraintEnd_toStartOf="@+id/three"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/one" />
        <Button
            android:id="@+id/three"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`3`)}"
            android:text="3"
            app:layout_constraintBottom_toTopOf="@+id/equal"
            app:layout_constraintEnd_toStartOf="@+id/minus"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/two" />
        <Button
            android:id="@+id/minus"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.operatorClicked(`-`)}"
            android:text="-"
            app:layout_constraintBottom_toTopOf="@+id/plus"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/three" />
        <Button
            android:id="@+id/four"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`4`)}"
            android:text="4"
            app:layout_constraintBottom_toTopOf="@+id/one"
            app:layout_constraintEnd_toStartOf="@+id/five"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />
        <Button
            android:id="@+id/five"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`5`)}"
            android:text="5"
            app:layout_constraintBottom_toTopOf="@+id/two"
            app:layout_constraintEnd_toStartOf="@+id/six"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/four" />
        <Button
            android:id="@+id/six"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`6`)}"
            android:text="6"
            app:layout_constraintBottom_toTopOf="@+id/three"
            app:layout_constraintEnd_toStartOf="@+id/multiply"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/five" />
        <Button
            android:id="@+id/multiply"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.operatorClicked(`*`)}"
            android:text="*"
            app:layout_constraintBottom_toTopOf="@+id/minus"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/six" />
        <Button
            android:id="@+id/seven"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`7`)}"
            android:text="7"
            app:layout_constraintBottom_toTopOf="@+id/four"
            app:layout_constraintEnd_toStartOf="@+id/eight"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />
        <Button
            android:id="@+id/eight"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`8`)}"
            android:text="8"
            app:layout_constraintBottom_toTopOf="@+id/five"
            app:layout_constraintEnd_toStartOf="@+id/nine"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/seven" />
        <Button
            android:id="@+id/nine"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.numberClicked(`9`)}"
            android:text="9"
            app:layout_constraintBottom_toTopOf="@+id/six"
            app:layout_constraintEnd_toStartOf="@+id/divide"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/eight" />
        <Button
            android:id="@+id/divide"
            style="@style/Calcbutton"
            android:onClick="@{()->simpleCalcViewModel.operatorClicked(`/`)}"
            android:text="/"
            app:layout_constraintBottom_toTopOf="@+id/multiply"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/nine" />
        <Button
            android:id="@+id/clear_all"
            style="@style/Calcbutton"
            android:layout_marginTop="8dp"
            android:onClick="@{()->simpleCalcViewModel.clearAllclicked()}"
            android:text="Clear"
            app:layout_constraintBottom_toTopOf="@+id/nine"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/result" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>               
Next is our MainActivity.kt

package com.arun.androidtutsforu.simplecalculator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
All our ui elements are managed by our fragment 
SimpleCalcFragment.kt

package com.arun.androidtutsforu.simplecalculator.calculator

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.arun.androidtutsforu.simplecalculator.R
import com.arun.androidtutsforu.simplecalculator.databinding.FragmentSimpleCalcBinding
class SimpleCalcFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentSimpleCalcBinding.inflate(inflater,container,false)
        val viewModel :SimpleCalcViewModel by activityViewModels()
        binding.simpleCalcViewModel =viewModel
        binding.setLifecycleOwner(this)
        return binding.root
    }
}
In new android architecture fragments should only display data. All the data calculation and decision making should be done in ViewModel
our SimpleCalcViewModel.kt
package com.arun.androidtutsforu.simplecalculator.calculator
import android.widget.Toast
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.math.floor
class SimpleCalcViewModel : ViewModel() {
    var secondNum  = 0.0
    var opcode :String =""
    var firstNumStr =""
    var secondNumStr =""
    var firstNum =0.0
    var isFirst:Boolean = true
    private var _number = MutableLiveData<String>()
    val number:LiveData<String>
     get() = _number
    private var _result = MutableLiveData<String>()
    val result:LiveData<String>
      get() = _result

    init{
      _number.value=""
      _result.value=""
    }
    fun numberClicked(num:String){
         _number.value = _number.value+num
        if(isFirst) {
            firstNumStr = firstNumStr + num
            firstNum =firstNumStr.toDouble()
        }else{
            secondNumStr = secondNumStr + num
            secondNum = secondNumStr.toDouble()
        }
    }
    fun operatorClicked(operator :String){

          _number.value=_number.value+operator
          opcode=operator
          isFirst=false

    }
    fun equalToClicked(){
        when(opcode){
            "+"->_result.value=(firstNum+secondNum).toString()
            "-"->_result.value=(firstNum-secondNum).toString()
            "*"->_result.value=(firstNum*secondNum).toString()
            "/"->_result.value=(firstNum/secondNum).toString()
            else->0
        }
        clear()
    }
    fun clearAllclicked(){
        clear()
        _number.value=""
        _result.value=""
    }
    fun clear(){
        isFirst=true
        firstNumStr=""
        secondNumStr=""
        firstNum=0.0
        secondNum=0.0
    }

}
You  can download full source code of this project from github 

Comments

Popular posts

Simple Calculator in Android

You can view new updated simple calculator with ViemModel and LiveData in my new blog    https://androidtuts4u.blogspot.com/2021/10/simple-calculator-with-viewmodel-and.html To create a calculator first  we need to create the layout of the calculator. Layout  is created  using XML file given below <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent" >  <EditText     android:id="@+id/result_id"       android:layout_width="fill_parent"     android:layout_height="120dp"   />  <Button    android:id="@+id/Btn7_id"      android:layout_width="70dp"    android:layout_height="60dp"    android:layout_below="@id/result_id"   ...

Keytool is not recognized as internal or extenal command / Adding PATH in system variable

If you are running a keytool command  keytool -list -v -keystore C:\Users\arun\.android\debug.keystore -alias androiddebugkey -storepass android    and getting an error   'keytool' is not recognized as an internal or external command  If you are using any other commad like java,javac , etc.. and getting an error " is not recognized as an internal or external command"  you can also use this same steps  you are getting this error because keytool.exe , executable file which exists in the bin directory of your JDK  is not added to Path in your Environmental variables. To resolve this issue 1 .first we need to find the bin Directory of our jdk    Usually this will be in  C:\Program Files\Java\jre1.8.0_221\bin (jre1.8.0_221 - change this to your latest version , ). you can see keytool.exe file in the bin directory . (If you installed jdk in a different directory Find your Jdk installation folder and  use that path....

Android Sqlite and ListView Example

This is simple application which insert data into Sqlite database --and shows the data  from the database in a ListView ListView is not used in android Anymore . We use RecyclerView and CardView   in Android RecyclerView Demo is available on the following link http://androidtuts4u.blogspot.in/2017/04/android-recyclerview-example.html RecyclerView with CardView Demo is available on the following link http://androidtuts4u.blogspot.in/2017/09/android-card-view-example.html This  is the first Activity of application which shows data from database in listview. Register here buton will start a Registration Activity. Submit button will add data to database and show it in the ListView of MainActivity. Update can be performed by clicking ListView items.     you can download the source code of this project from  google drive   https://drive.google.com/folderview?id=0BySLpWhqmbbdS0dtT1R2TXdBWEE&usp=sharing click on the abov...