Android Tutorial: Calculator App

With this blog post you can build an Android calculator app for calculating different absolute outcomes for different sets of discount percentages. It’s a simple app were the user can set e.g. the price of a retail item and calculate his/her savings and final price when the retail price gets discounted with a certain percentage (e.g. 25%). 

This app is not that serieus at all,  but you can learn the follow concepts in Android:

- Apply a Seekbar widget for setting the percentage.
- Apply TextView to set calculation outcomes
- Use EditText to handle user input
- Use an ImageView to set a banner
- Use a custom font in your app (added to this tutorial).

In case you want to see the app working on your device, scroll to the bottom of this post for the link to the Android Play Market.

Let’s start by creating the XML Layout of our calculation App.  I used a banner on top of the layout, this is ofcourse optional for finishing this tutorial. You can add the banner to your drawable folder of your project. The layout is very straightforward. Notice that I used a few TextViews to set static headers in the app.

Worth mentioning are the following parts of the EditText View. The Hint refers to the grayed out text before the user put a number in the EditText, this helps the user to recognize the type of input field. I also set the EditText to ‘number|numberDecimal’ allowing the user to enter a price with a decimal point.

android:hint="€ 0,00"

android:inputType="number|numberDecimal"

Complete XML Layout:

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

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/bannershopper" />

    <TextView
        android:id="@+id/tv_static_finalprice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/imageView1"
        android:layout_marginLeft="17dp"
        android:layout_marginTop="33dp"
        android:text="Your final price:"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/tv_static_yourdiscount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_static_finalprice"
        android:layout_below="@+id/tv_static_finalprice"
        android:layout_marginTop="26dp"
        android:text="Your discount:"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/tv_amount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_static_finalprice"
        android:layout_alignBottom="@+id/tv_static_finalprice"
        android:layout_marginLeft="22dp"
        android:layout_toRightOf="@+id/tv_static_finalprice"
        android:text="€ 0,00"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/tv_discount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/tv_static_yourdiscount"
        android:layout_alignBottom="@+id/tv_static_yourdiscount"
        android:layout_alignLeft="@+id/tv_amount"
        android:text="€ 0,00"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <EditText
        android:id="@+id/etsetamount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_static_yourdiscount"
        android:layout_centerVertical="true"
        android:ems="10"
        android:hint="€ 0,00"
        android:inputType="number|numberDecimal"/ >



    <TextView
        android:id="@+id/tv_percent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/etsetamount"
        android:layout_marginTop="74dp"
        android:paddingRight="@dimen/padding"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/tv_percent"
        android:layout_alignLeft="@+id/etsetamount"
        android:layout_alignRight="@+id/tv_discount"
        android:max="100"
        android:progress="0" 
        android:paddingTop="10dp" 
        android:paddingBottom="10dp" 
        android:minHeight="6dip"
        android:maxHeight="6dip" />

    <TextView
        android:id="@+id/tvdrag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/seekBar1"
        android:layout_alignLeft="@+id/seekBar1"
        android:layout_marginBottom="16dp"
        android:text="Set your discount %" />

</RelativeLayout>

When you have entered this layout, your app should look something like the screenshot below. It could differ depending on the API level you used.

To get our calculator app working we have to build our Java class. The complete Java code is set below. When you accept all the imports, your Java file still gives some errors for the custom font implementation. See down in this blog post as you are missing a ttf file in your project.

 

 

 

 

The complete Java class:

package com.peeters.christian;

import java.text.DecimalFormat;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Typeface;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends Activity {

EditText etsetamount;

TextView tvamount, tvdiscount, tvpercentage, staticfinalprice, staticdiscount, staticsetpercentage;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

etsetamount = (EditText)findViewById(R.id.etsetamount);
tvamount = (TextView)findViewById(R.id.tv_amount);
tvdiscount = (TextView)findViewById(R.id.tv_discount);
staticfinalprice = (TextView)findViewById(R.id.tv_static_finalprice);
staticdiscount = (TextView)findViewById(R.id.tv_static_yourdiscount);
staticsetpercentage = (TextView)findViewById(R.id.tvdrag);
tvpercentage = (TextView)findViewById(R.id.tv_percent);

SeekBar sb = (SeekBar)findViewById(R.id.seekBar1);
sb.setMax(20);
sb.setProgress(0);

Typeface font = Typeface.createFromAsset(getAssets(), "appleberry_with_cyrillic.ttf");
etsetamount.setTypeface(font);
tvamount.setTypeface(font);
tvdiscount.setTypeface(font);
tvpercentage.setTypeface(font);
staticfinalprice.setTypeface(font);
staticdiscount.setTypeface(font);
staticsetpercentage.setTypeface(font);

sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
int progress5 = progress *5;
tvpercentage.setText(Integer.toString(progress5)+ "%");

try{
float finalprice = Float.valueOf(etsetamount.getText().toString());
tvamount.setText("€"+ new DecimalFormat("#,###,###.##").format((1-(progress5 / 100.0f)) * finalprice));
tvdiscount.setText("€"+ new DecimalFormat("#,###,###.##").format((progress5 / 100.0f) * finalprice));
}catch(NumberFormatException e){

}
}
});
}
}

At first I have set the EditText and TextView variables as global variables (above the OnCreate method) so we can easily access them later on in the Seekbar methods. When you create the reference to the Seekbar in your Oncreate method, make sure you let Eclipse/Android SDK implement the unimplemented methods.

SeekBar sb = (SeekBar)findViewById(R.id.seekBar1);

You can set also the Maximum value (20 in my case) and set the starting point of the seekbar (0 in my case).

sb.setMax(20);
sb.setProgress(0);

Note that the app will have a Seekbar range from 0-100% despite that I have set the Max to 20. The reason is that I want to have a seekbar increment of 5. I multiply this number later in the Seekbar method by 5 (int progress5 = progress * 5). Progress is the variable defined in the Seekbar as the value which the user has set.  Oh yeah, 20 * 5 = 100% ;)

Let’s shortly discuss the key method of the application: the value setting of the Seekbar and than the calculations which are set to the TextViews.

@Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
int progress5 = progress *5;
tvpercentage.setText(Integer.toString(progress5)+ "%");
try{

float finalprice = Float.valueOf(etsetamount.getText().toString());
tvamount.setText("€"+ new DecimalFormat("#,###,###.##").format((1-(progress5 / 100.0f)) * finalprice));
tvdiscount.setText("€"+ new DecimalFormat("#,###,###.##").format((progress5 / 100.0f) * finalprice));

}catch(NumberFormatException e){

}

}

});

As you can see we use the standard SDK method onProgressChanged, it creates a variable Progress which holds the value to which the user has dragged the seekbar. We parse this value to a String and set it in the TextView “tvpercentage”  This is the TextView right next to the Seekbar so the user knows which value he/she has selected.

Second we have a Try/Catch block to do some calculations.

float finalprice = Float.valueOf(etsetamount.getText().toString());

tvamount.setText("€"+ new DecimalFormat("#,###,###.##").format((1-(progress5 / 100.0f)) * finalprice));

tvdiscount.setText("€"+ new DecimalFormat("#,###,###.##").format((progress5 / 100.0f) * finalprice));

First we get the amount which the user has manually provided through the EditText: etsetamount, we set this value as a String and create a float variable (so it allows decimal points).

The finalprice which is the price e.g. on a price tag without the discount is then used in the tvamount and tvdiscount TextViews. The calculations are based on 2 elements. (1) to allow for a DecimalFormat and (2) to calculate the new retail price (1-(progress5 / 100.0f)) * finalprice) and calculate the discount (progress5 / 100.0f) * finalprice).

There is not much more, as you can see it’s very simple to create a small android application which does some calculations based on pre-set values.

In addition, I have set a custom font in this app. The Android SDK only provides 3 standard fonts (monospace, serif, sans). In case you want to use your own custom font you have to upload the font file in your assets folder and set the reference programmatically.

First download a font type. I have downloaded and use the appleberry_with_cyrillic.ttf. Copy and paste this ttf file in your assets folder. You can find free fonts via http://www.1001freefonts.com.  It could be that the folder doesn’t exist yet in your project, in that case create an assets folder.

Return back to your Java file and set all your TextViews and EditText to this new font. First create the reference to your asset folder and set all your textviews via setTypeface to your new font variable (font). In this tutorial I have set all TextView manually to the new fonttype: font. When you have a lot of TextView your are probably better of by creating a separate class.

Typeface font = Typeface.createFromAsset(getAssets(), "appleberry_with_cyrillic.ttf");
etsetamount.setTypeface(font);
tvamount.setTypeface(font);
tvdiscount.setTypeface(font);
tvpercentage.setTypeface(font);
staticfinalprice.setTypeface(font);
staticdiscount.setTypeface(font);
staticsetpercentage.setTypeface(font);

 

You can download this app via the Play Market:

3 Responses

  1. John September 8, 2012 / 5:52 pm

    Great tutorial. I’m new to Android programming but this absolutely helps to get me started. Keep them coming please :)

  2. Chris November 1, 2012 / 3:21 pm

    Hi,

    Could you post the whole source code for this tutorial? As I can’t get it to work the application crashes when I open it. You haven’t showed what to put in strings.xml.

    Thanks.

Leave a Reply to John Cancel reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*