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 application like this 1.  Create a class which extends  

Android CardView And SQLite example

SQLite Database Android provides several options to save persistent application data. SQlite database is ideal for saving repeating and structured data . Using Sqlite we can save structured data in a private database.  This is a simple application showing use of Sqlite database in android . This example shows how to perform Insert , select , update and delete operation in  SQlite database Screenshots of our sample application                                                                                                                      This is a Registration app. New user can register by clicking registration button . Registered  users are shown in cards below that button . we can update or delete registered users by clicking overflow menu in each card. 1.First we need to create database for our application .    a. Create a contract class .Contract class contains constants that defines names of Tables and columns of our database. Contract class allows us

How to install eclipse tar.gz file in ubuntu 12.04

eclipse-SDK-3.7-linux-gtk-x86_64.tar.gz  file can be installed in ubuntu 12.04  like this  1. dowload latest version of eclipse from here   2. extract the eclipse-SDK-3.7-linux-gtk-x86_64.tar.gz file 3. move extracted file to /opt/  directory       mv eclipse /opt/      sudo chown -R root:root eclipse      sudo chmod -R +r eclipse 4. create eclipse exectable in your path      sudo touch /usr/bin/eclipse    sudo chmod 755 /usr/bin/eclipse    sudo nano /usr/bin/eclipse 5. copy this into nano      #!/bin/sh   #export MOZILLA_FIVE_HOME="/usr/lib/mozilla/"   export ECLIPSE_HOME="/opt/eclipse"    $ECLIPSE_HOME/eclipse $* 6. save file using ctrl+o  exit with ctrl+x 7. create gnome menu item        sudo nano /usr/share/applications/eclipse.desktop 8. copy this into nano          [Desktop Entry]    Encoding=UTF-8    Name=Eclipse    Comment=Eclipse IDE    Exec=eclipse    Icon=/opt/eclipse/icon.xpm    Terminal=false    Type=A