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

How to Open Android Emulator form Command Line and install Apk in Emulator

  You can also view this on my youtube channel How to Open Android Emulator from Commad Line 1.Open Command line 2.Change working directory to android sdk directory    cd  appdata/local/android/sdk/emulator 3.List all available Android virtual devices     emulator -list-avds 4. All your avds will be shown choose the avd_name you want to open    emulator -avd avd_name   5.Your Android virtual device will open up How to install APk file to emulator Drag the APK to Android emulator it will install automatically

Android List View using Custom Adapter and SQLite

following is a simple applicaton to create ListView using  Custom adapter.screenshot of the application  is like this . 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 Example is available on the following link http://androidtuts4u.blogspot.in/2017/09/android-card-view-example.html The ListView below the submit button is populated using Custom Adapter.Data is stored and retrieved using SQLite databsase. you can download the source code of this project from  google drive   https://drive.google.com/folderview?id=0BySLpWhqmbbdUXE5aTNhazludjQ&usp=sharing click on the above link ->sign into  your  google account ->add this to your google drive -> open it in google drive and download it. To create a simple ...