Introduction
One of the cool things about having a smart phone is knowing that you will always have a calculator handy. If you need to total receipts, perform some supermarket comparisons, or calculate tips or percentages on the fly a calculator is definitely a handy tool.
Screenshot of the calculator tutorial |
The Layout
This layout could admittedly be improved upon. The focus of this tutorial is about bringing together all of the pieces rather than creating a beautiful looking program, so we really just want something functional. Listed below is the xml code for the layout.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="50dip"/> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:id="@+id/buttonLeftParen" android:text="(" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonRightParen" android:text=")" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonBackspace" android:layout_weight="1" android:text="B" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonClear" android:text="C" android:layout_weight="1" android:layout_width="fill_parent"></Button> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:id="@+id/button7" android:text="7" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button8" android:text="8" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button9" android:text="9" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonPlus" android:text="+" android:layout_weight="1" android:layout_width="fill_parent"></Button> </LinearLayout> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:id="@+id/button4" android:text="4" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button5" android:text="5" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button6" android:text="6" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonMinus" android:text="-" android:layout_weight="1" android:layout_width="fill_parent"></Button> </LinearLayout> <LinearLayout android:id="@+id/linearLayout4" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:id="@+id/button1" android:text="1" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button2" android:text="2" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/button3" android:text="3" android:layout_weight="1" android:layout_width="fill_parent"></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonTimes" android:text="*" android:layout_weight="1" android:layout_width="fill_parent"></Button> </LinearLayout> <LinearLayout android:id="@+id/linearLayout5" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_weight="1" android:id="@+id/button0" android:text="0"></Button> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_weight="1" android:id="@+id/buttonDecimal" android:text="."></Button> <Button android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_weight="1" android:id="@+id/buttonEquals" android:text="="></Button> <Button android:layout_height="wrap_content" android:id="@+id/buttonDivide" android:text="/" android:layout_width="fill_parent" android:layout_weight="1"></Button> </LinearLayout> </LinearLayout>
The layout is pretty straightforward, a bunch of rows with buttons in them. This layout uses a combination of linear layouts, whereas a table layout could also be suited.
As I mentioned in my layout tutorial, it is often a good idea to sketch out what you want beforehand, because it is much easier to make changes on paper and make the XML once. Regretfully, I did not follow my own advice when I wrote this tutorial...
The Secret
So know we have a bunch of buttons that we can use to have the user add input, but how do we actually crunch the numbers? Remember the "Golden Rule" of programming. Reuse code and don't try to reinvent the wheel!
The display at the top is actually a WebView. Using a webview instead of a TextView gives us extra formatting options, and also allows us to leverage the power of JavaScript.
JavaScript has a built in "eval" function that will take a string as an argument and run that string as JavaScript code. Our string will just be a bunch of math that we want to compute, and JavaScript will handle all the work for us.
Enabling JavaScript for the WebView
It is important to note that the WebView by default does not have javascript enabled. Use the code below to enable JavaScript in the WebView.
// Enable javascript for the view mWebView = (WebView) findViewById(R.id.webview); mWebView.getSettings().setJavaScriptEnabled(true);
Button Listeners and String Builders
The calculator works by storing the user inputs in a String Builder and passing this information to the web view for evaluation. StringBuilders are used instead of strings because they are more efficient when you are constantly changing values.
We will use one button listener for all of the buttons. For most of the buttons, what we want to append to the string is exactly what the button is displaying. This makes the listener code fairly simple.
private class ButtonClickListener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.buttonBackspace: if(mMathString.length() > 0) mMathString.deleteCharAt(mMathString.length()-1); break; case R.id.buttonClear: if(mMathString.length() > 0) mMathString.delete(0, mMathString.length()); break; default: mMathString.append(((Button) v).getText()); } updateWebView(); }
Updating the WebView
You will notice that the listener calls a function to update the web view. This function creates a simple string of html to display everytime it is called. I believe there is a way to more fully integrate the JavaScript handler with the Android App, but for the small amount of computation we are doing it is probably not worth it right now.
private void updateWebView() { StringBuilder builder = new StringBuilder(); builder.append("<html><body>"); builder.append("<script type=\"text/javascript\">document.write('"); builder.append(mMathString.toString()); builder.append("');"); builder.append("document.write('<br />=' + eval(\""); builder.append(mMathString.toString()); builder.append("\"));</script>"); builder.append("</body></html>"); mWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
I tried to split up the building of the string into smaller chunks in order to improve readability. As you can see, it can get pretty difficult to read fairly quickly.
The App in Action
Listed below is a screenshot from the app.
A screenshot of the calculator evaluating an expression |
There are a number of areas in which this app could be improved, and if there is interest, I may do a follow up tutorial.
- Design a better layout
- Format the output better
- Free text input
- More advanced math functions (sine, cosine, etc...)
Full Code for Activity
Listed below is the full code for the activity.
package com.androiddom.calculatortest; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebView; import android.widget.Button; public class CalculatorActivity extends Activity { private WebView mWebView; private StringBuilder mMathString; private ButtonClickListener mClickListener; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create the math string mMathString = new StringBuilder(); // Enable javascript for the view mWebView = (WebView) findViewById(R.id.webview); mWebView.getSettings().setJavaScriptEnabled(true); // Set the listener for all the buttons mClickListener = new ButtonClickListener(); int idList[] = { R.id.button0, R.id.button1, R.id.button2, R.id.button3, R.id.button4, R.id.button5, R.id.button6, R.id.button7, R.id.button8, R.id.button9, R.id.buttonLeftParen, R.id.buttonRightParen, R.id.buttonPlus, R.id.buttonPlus, R.id.buttonMinus, R.id.buttonDivide, R.id.buttonTimes, R.id.buttonDecimal, R.id.buttonBackspace, R.id.buttonClear }; for(int id : idList) { View v = findViewById(id); v.setOnClickListener(mClickListener); } } private void updateWebView() { StringBuilder builder = new StringBuilder(); builder.append("<html><body>"); builder.append("<script type=\"text/javascript\">document.write('"); builder.append(mMathString.toString()); builder.append("');"); builder.append("document.write('<br />=' + eval(\""); builder.append(mMathString.toString()); builder.append("\"));</script>"); builder.append("</body></html>"); mWebView.loadData(builder.toString(), "application/xhtml", "UTF-8"); } private class ButtonClickListener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.buttonBackspace: if(mMathString.length() > 0) mMathString.deleteCharAt(mMathString.length()-1); break; case R.id.buttonClear: if(mMathString.length() > 0) mMathString.delete(0, mMathString.length()); break; default: mMathString.append(((Button) v).getText()); } updateWebView(); } }
------------------------------------------------------------
We create these tutorials in our free time. If you like what you see please consider buying us a cup of coffee so we can keep creating useful material. Click on the image below to make a donation via Paypal.
This comment has been removed by the author.
ReplyDeleteI can not see the numbers on the WebView. I need to install some plugin?
ReplyDeleteThank you.
Diego, Brazil
i want to create an html app which should work as an app but offline. It shouldnot connect to internet. Please help me..
ReplyDeleteMy mail id is shyjumon.thomas@gmail.com.
jaa re edi k,,,,,
Deletehi thanks...
ReplyDeleteI can not see the numbers on the WebView...its not working help me my mail id:karthiktokeyan@gmail.com
replace:
DeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", "UTF-8");
Hi Karthik,
ReplyDeleteDo you get any compiler errors? Or any other messages?
THANK YOU! :) - racrecio
ReplyDeleteThanks for the cool post
ReplyDeleteim not getting any no. on tht pad help me pla my emailid is penubarthy@gmail.com and im not gtng any compile time errors
ReplyDeletereplace:
DeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", "UTF-8");
im not getting any numbers too on webview. can someone help me? email: mikac.matija@gmail.com tnx
ReplyDeletereplace:
DeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", "UTF-8");
thnxx man..dat did d work fa me..
ReplyDeleteHi, Thanks for the Post. :) But I am getting Null pointer exception in the activityFile at line no 27 . that is while doingmWebView.getSettings() , I think (WebView) findViewById(R.id.webview); is returning NULL. I am not getting whats the problem. Can ANyone help me?? My email Id is sachinpattan@gmail.com
ReplyDeletereally superb man... thanks for posting .. can u pls send some examples coding and especially virtual keyboard in andriod ...to me my mail adress is renganarundx@gmail.com
ReplyDeleteGive me the same thing using textview instead of webview
ReplyDeleteNice tutorial.. but what will it do when i press equals? ... i mean i have case R.id.buttonEquals:
ReplyDeletemMathString.
break;
what is behind mMathString?
mMathString like its name describes is just a string.
DeleteWe are using Javascript to do the operations for us:
"JavaScript has a built in "eval" function that will take a string as an argument and run that string as JavaScript code. Our string will just be a bunch of math that we want to compute, and JavaScript will handle all the work for us."
So, basically we are passing a string to javascript and it returns the result.
Great, awesome logic used simplifies the program greatly !Keep it up, loved the logic u used because normally doing it using a single view will take tons of code !
DeleteGreat tut! Thanks a lot! :D
ReplyDeleteYou are welcome, glad it helped.
Deletewhen i copy the code in eclipse it gives me an error on all the R.id's it puts the red line under id help
ReplyDeleteDo you have your android sdk properly set up?
DeleteR is a generated class, if eclipse is set up properly with the sdk it should work.
go to eclipse and select Project nd select Build All option.
DeleteThen that error will be deleted
thanks a lot
ReplyDeleteYou are welcome :)
Deleteim not getting any no. on tht pad help me please. my emailid is harikaharikrishna6@gmail.com and im not gtng any compile time errors
ReplyDeletereplace:
DeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", "UTF-8");
Thnx dude..This made my day
ReplyDeletegreat man.keep posting
ReplyDeleteThank you! We're open to suggestions for future tutorials.
DeleteThis comment has been removed by the author.
ReplyDeletethere is any simple code!!!
ReplyDeletei am getting an error saying to remove onclick() bec of multiple marks..
ReplyDeleteplease help me...
hey man if i click C button it shows "=undefined"
ReplyDeletewhat is the prb?
operation working perfect but thi =undefinied is what ?
when i copy that code of calculator
ReplyDeletemy calculator is made very esayly
i have no error in program but when i run there is show an eror msg tha "the application calculator has stop unexpectedly.please try again"..is there something missing..?????? may be in string.xml or androidmanifest.xml..??
ReplyDeletethnx mate..nice programming logic...
ReplyDeleteI too am able to compile with no errors, buttons work great, but no numbers or values of the buttons show. Can someone please help me out? Jake.Koll21@gmail.com. Thank you.
ReplyDeleteThe webView doesn't display any text.
ReplyDeleteI don't know why , tried coloring text & all that color stuff.
But, nope it doesn't work.
While, I loved the code.
I am eager to add it to my calc.
Also, can you tell me adding wolfram API for integration.
Thanks in advance.
My email ID : akshaychordiya2@gmail.com
how can i get the result displayed in the webview. i need it to store in a string in order to use it.. plz ans...
ReplyDeletehow to resolved the =undefined when i click the "b button" and "c button" i think it must clear the webview? please help me email me at jefesanes@yahoo.com
ReplyDeleteI copied the Final Code 1to1 just to understand it first. However nothing is happening. The App loads in the VM but my button pushes aren't being captured by the OnClickListener :(
ReplyDeleteAm I missing something?
replace:
DeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", "UTF-8");
I implemented this code in my app and Ive also read that numbers aren't showing up for some people.
ReplyDeleteI have both both a physical DroidX, code works perfectly, and a Asus TF101 Tablet, which shows the calculator but does not show number input. I am trying to narrow down what the issue is but maybe this info will help someone do it faster than me. I am guessing incompatibility with versions?
DroidX 2.3.4
TF101 4.0.3
can any one explain why not webview displaying any numbers please??
ReplyDeletei guess this might be a solution...
ReplyDeletereplace:
mWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
with:
mWebView.loadData(builder.toString(), "text/html", null);
i know that UTF-8 is correct encoding, but for me second-one works..
Regards,
HBK
Didn't work first,
Deletewith this change it diplays correctly on my tf300t
right.you change text/html to text/xml.
DeleteHi! Thanks for this! its works for me :D
DeleteI also cannot see the text in web view, just wanted to know if there is any plugin or some other stuff I need to download. My email is sheilsarda@yahoo.com. By the way, very nice step by step tutorials.
ReplyDeletei need to create calculator of laos version so would help me
ReplyDeletei have fix tool of boss.dont show any text when you are click.
ReplyDeletemWebView.loadData(builder.toString(), "application/xhtml", "UTF-8");
replace by :
webview.loadData(builder.toString(), "application/xml", "UTF-8");
so i have code actuarly is running very good.
ReplyDeleteend the last ,thank you boss.so boss have help you
trust that i will be success
Did you solve "C" button problem?
DeleteWhen I press "C" it show's undefined message!
ReplyDeleteWhat should be add to correct this one?
How do you make the calculator to occupy the whole screen?
ReplyDeleteThank you, it is very usefull app! also thank you Anonymous for giving that code
ReplyDeletemWebView.loadData(builder.toString(), "text/html", null);
it works for me:)
android is best os
ReplyDeleteThe Ce undefined problem can be solved by adding a flag value to switch case in public void onClick(View v) {
ReplyDeleteswitch (v.getId()) {
case R.id.but_del:
if(mMathString.length() > 0)
mMathString.deleteCharAt(mMathString.length()-1);
break;
case R.id.but_Clear:
if(mMathString.length() > 0)
mMathString.delete(0, mMathString.length());
flag = 0;
break;
default:
flag = 1;
mMathString.append(((Button) v).getText());
}
and accordingly add mWebView.loadData(builder.toString(), "text/html", null);
if(flag == 0)
{
mWebView.loadData("", "text/html",null);
}
When I click the buttons a toast is displayed as "Downloading not supported" What should I do?
ReplyDeletePlease Help me..
my e-mail : vihangarajalingam7@gmail.com
Thanks.
pls send full source code
ReplyDeletemy e-mail : prakharc0887@gmail.com
unable to see the text displayed on the webtext. the code is working error free.
ReplyDeleteplease share the details
sakshinarang57@gmail.com
thank U so much :) :) :) i find ur post most useful to me as it is simple n effective than other calculator source codes for android tq so much...
ReplyDeleteim tryna make calculator app for android which uses custom buttons....
but i have a problem... getText() is not working coz i didnt menntion android:text in xml...
can u sugest me few solutions...
Thanku so much for ur beautiful idea... :D
myemail id: avinashlegendkiller@gmail.com
ReplyDeleteThis comment has been removed by the author.
ReplyDeletei am new in android and have a question: how this program do the math part?
ReplyDeleteHi
ReplyDeleteI have some problem with the calculator. The AVD keep showing the "app has stopped". Then it automatically closes it. May I know how to resolve this issue? What could the likely problem be?
I have same problem of "Unfortunately app has stopped" when I press any button of calculator.
ReplyDeletei have created calculator app by this tutorial,but after created nothing will happend!no string ,no answer
ReplyDeleteplease help me
ReplyDeletemy id is: lax.khushi@gmail.com
ReplyDeletehow can we make same calculator without using eval function????
ReplyDeleteplease help???
my email id is: agrwalakanksha@gmail.com
ReplyDeleteAndroid Development Tutorial: Creating a Simple Basic Calculator : https://www.youtube.com/watch?v=8gE5pQNK3Wc
ReplyDeletenice but difficult for beginners..to learn step by step process visit http://infoocode.blogspot.com/2015/11/Simple-android-calculator-code.html
ReplyDeleteThis tutorial was very helpful to build my basics. I was able to build my own app for Play store. Thank you Sir.
App Link : https://goo.gl/oMlqmn
Hello, and thank you for this tutorial,
ReplyDeleteI do have a problem I have to implement a code ''Enabling JavaScript for the WebView'' but I don't have any idea where I have to put it. Can not see any info on the location.
Can you provide me the name of the file and the location.
Thank you.
beyrendchristian@gmail.com
How to save each file
ReplyDelete