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

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 ...

Controlling Back button Behavior in Fragment-- kotlin

when user navigates in an application android maintains back stack of destinations . This allows android to go back to previous destination when user clicks back button . some  times we  need to implement our own back button behavior  for best user experience . For example  if we are in a timer based quiz  application . when the user clicks on the back button if we go back to the previous destination without stopping  the counter , it will crash  the application . So first we need to know whether the  user  pressed the back button accidentally or not by  using a dialogue box . If the user want to go back to previous destination  we need to stop the counter and  then go back to the previous destination. We can control the back button hahavior byusing OnBackPressedDispatcher  . This controls how back button events are dispatched to one or more onBackPressedCallback objects . callbacks are added using addCallback methods. e...

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...