Welcome to part 4 of my Android Development Tutorial. In the last part, I showed you how to put together an Android User Interface. This time I will add to that app in a big way!
Over the course of this tutorial and the next I will cover RadioButtons, RadioGroups, CheckBoxes, DropDows (Spinners), Buttons, Chronometers, ChangeListeners, ItemSelectedListeners, onClickListeners and much more. All of the code below should help you along.
If you like videos like this, it helps to tell Google+ with a click here [googleplusone]
Code From the Video
activity_crazy_tip_calc.xml
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".CrazyTipCalc" > <requestFocus /> <TextView android:id="@+id/billTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="14dp" android:layout_marginTop="14dp" android:text="@string/bill_text_view" /> <!-- android:ems defines the width of the EditText box --> <EditText android:id="@+id/billEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_toRightOf="@+id/billTextView" android:ems="5" android:inputType="numberDecimal" android:text="@string/bill_edit_text" > <requestFocus /> </EditText> <TextView android:id="@+id/tipTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/billTextView" android:layout_marginLeft="15dp" android:layout_toRightOf="@+id/billEditText" android:text="@string/tip_text_view" /> <EditText android:id="@+id/tipEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/finalBillTextView" android:layout_marginLeft="18dp" android:layout_toRightOf="@+id/tipTextView" android:ems="4" android:inputType="numberDecimal" android:text="@string/tip_edit_text" /> <TextView android:id="@+id/finalBillTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/finalBillEditText" android:layout_below="@+id/billEditText" android:layout_marginTop="14dp" android:text="@string/final_bill_text_view" /> <EditText android:id="@+id/finalBillEditText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/tipEditText" android:layout_below="@+id/finalBillTextView" android:ems="5" android:inputType="numberDecimal" android:text="@string/final_bill_edit_text" /> <TextView android:id="@+id/changeTipTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/finalBillTextView" android:layout_alignLeft="@+id/billTextView" android:text="@string/change_tip_text_view" /> <!-- android:progress="15" defines the default for the SeekBar --> <SeekBar android:id="@+id/changeTipSeekBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/changeTipTextView" android:layout_alignTop="@+id/finalBillEditText" android:layout_marginTop="14dp" android:layout_toLeftOf="@+id/tipTextView" android:progress="15" /> <!-- NEW STUFF --> <TextView android:id="@+id/IntroTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/changeTipSeekBar" android:layout_below="@+id/changeTipSeekBar" android:layout_marginTop="16dp" android:text="@string/intro_text_view" /> <CheckBox android:id="@+id/friendlyCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/IntroTextView" android:layout_below="@+id/IntroTextView" android:text="@string/intro_friendly_text_view" /> <CheckBox android:id="@+id/specialsCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/friendlyCheckBox" android:layout_alignBottom="@+id/friendlyCheckBox" android:layout_alignRight="@+id/finalBillTextView" android:layout_marginRight="26dp" android:text="@string/intro_specials_text_view" /> <CheckBox android:id="@+id/opinionCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/specialsCheckBox" android:layout_alignBottom="@+id/specialsCheckBox" android:layout_toRightOf="@+id/specialsCheckBox" android:text="@string/intro_opinion_text_view" /> <RadioGroup android:id="@+id/availableRadioGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/IntroTextView" android:layout_alignRight="@+id/finalBillTextView" android:layout_below="@+id/availabilityTextView" android:layout_marginTop="15dp" android:orientation="horizontal" > <RadioButton android:id="@+id/availableBadRadio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="@string/available_bad_radiobutton" /> <RadioButton android:id="@+id/availableOKRadio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/available_ok_radiobutton" /> <RadioButton android:id="@+id/availableGoodRadio" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/available_good_radiobutton" /> </RadioGroup> <TextView android:id="@+id/availabilityTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/availableRadioGroup" android:layout_below="@+id/friendlyCheckBox" android:layout_marginTop="12dp" android:text="@string/available_text_view" /> <Spinner android:id="@+id/problemsSpinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/availableRadioGroup" android:layout_alignRight="@+id/opinionCheckBox" android:layout_below="@+id/availableRadioGroup" android:layout_marginTop="11dp" android:entries="@array/problem_solving" /> <TextView android:id="@+id/timeWaitingTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/problemsSpinner" android:layout_below="@+id/problemsSpinner" android:layout_marginTop="12dp" android:text="@string/time_waiting_text_view" /> <Chronometer android:id="@+id/timeWaitingChronometer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/timeWaitingTextView" android:layout_toRightOf="@+id/tipTextView" android:text="Chronometer" /> <Button android:id="@+id/startChronometerButton" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/timeWaitingTextView" android:layout_below="@+id/timeWaitingChronometer" android:layout_marginTop="16dp" android:text="@string/start_chronometer_button" /> <Button android:id="@+id/pauseChronometerButton" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/startChronometerButton" android:layout_toRightOf="@+id/availabilityTextView" android:text="@string/pause_chronometer_button" /> <Button android:id="@+id/resetChronometerButton" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/pauseChronometerButton" android:layout_toRightOf="@+id/changeTipSeekBar" android:text="@string/reset_chronometer_button" /> <!-- END OF NEW STUFF --> </RelativeLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CrazyTipCalc</string> <string name="action_settings">Settings</string> <string name="bill_text_view">Bill</string> <string name="bill_edit_text">0.0</string> <string name="tip_text_view">Tip</string> <string name="tip_edit_text">.15</string> <string name="final_bill_text_view">Final Bill</string> <string name="final_bill_edit_text">0.0</string> <string name="change_tip_text_view">Change Tip</string> <!-- END OF FIRST PART --> <string name="intro_text_view">Introduction</string> <string name="intro_friendly_text_view">Friendly</string> <string name="intro_specials_text_view">Specials</string> <string name="intro_opinion_text_view">Opinion</string> <string name="available_text_view">Availability</string> <string name="available_bad_radiobutton">Bad</string> <string name="available_ok_radiobutton">OK</string> <string name="available_good_radiobutton">Good</string> <string name="time_waiting_text_view">Time Waiting for Service</string> <string name="start_chronometer_button">Start</string> <string name="pause_chronometer_button">Pause</string> <string name="reset_chronometer_button">Reset</string> <!-- Spinner Options --> <string-array name="problem_solving"> <item>Problem Solving</item> <item>Bad</item> <item>OK</item> <item>Good</item> </string-array> </resources>
CrazyTipCalc.java
package com.newthinktank.crazytipcalc; import android.os.Bundle; import android.os.SystemClock; import android.app.Activity; import android.text.Editable; import android.text.TextWatcher; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.Chronometer; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.Spinner; import android.widget.TextView; public class CrazyTipCalc extends Activity { // Constants used when saving and restoring private static final String TOTAL_BILL = "TOTAL_BILL"; private static final String CURRENT_TIP = "CURRENT_TIP"; private static final String BILL_WITHOUT_TIP = "BILL_WITHOUT_TIP"; private double billBeforeTip; // Users bill before tip private double tipAmount; // Tip amount private double finalBill; // Bill plus Tip EditText billBeforeTipET; EditText tipAmountET; EditText finalBillET; // NEW PART --------------- // Sum of all radio buttons and check boxes private int[] checklistValues = new int[12]; // Declare CheckBoxes CheckBox friendlyCheckBox; CheckBox specialsCheckBox; CheckBox opinionCheckBox; // Declare RadioButtons RadioGroup availableRadioGroup; RadioButton availableBadRadio; RadioButton availableOKRadio; RadioButton availableGoodRadio; // Declare Spinner (Drop Down Box) Spinner problemsSpinner; // Declare Buttons Button startChronometerButton; Button pauseChronometerButton; Button resetChronometerButton; // Declare Chronometer Chronometer timeWaitingChronometer; // The number of seconds you spent // waiting for the waitress long secondsYouWaited = 0; // TextView for the chronometer TextView timeWaitingTextView; // END OF NEW PART --------------- @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crazy_tip_calc); // Inflate the GUI // Check if app just started, or if it is being restored if(savedInstanceState == null){ // Just started billBeforeTip = 0.0; tipAmount = .15; finalBill = 0.0; } else { // App is being restored billBeforeTip = savedInstanceState.getDouble(BILL_WITHOUT_TIP); tipAmount = savedInstanceState.getDouble(CURRENT_TIP); finalBill = savedInstanceState.getDouble(TOTAL_BILL); } // Initialize the EditTexts billBeforeTipET = (EditText) findViewById(R.id.billEditText); // Users bill before tip tipAmountET = (EditText) findViewById(R.id.tipEditText); // Tip amount finalBillET = (EditText) findViewById(R.id.finalBillEditText); // Bill plus tip // Initialize the SeekBar and add a ChangeListener tipSeekBar = (SeekBar) findViewById(R.id.changeTipSeekBar); tipSeekBar.setOnSeekBarChangeListener(tipSeekBarListener); // --------------------------- // Add change listener for when the bill before tip is changed billBeforeTipET.addTextChangedListener(billBeforeTipListener); // NEW PART --------------- // Initialize CheckBoxs friendlyCheckBox = (CheckBox) findViewById(R.id.friendlyCheckBox); specialsCheckBox = (CheckBox) findViewById(R.id.specialsCheckBox); opinionCheckBox = (CheckBox) findViewById(R.id.opinionCheckBox); setUpIntroCheckBoxes(); // Add change listeners to check boxes // Initialize RadioButtons availableBadRadio = (RadioButton) findViewById(R.id.availableBadRadio); availableOKRadio = (RadioButton) findViewById(R.id.availableOKRadio); availableGoodRadio = (RadioButton) findViewById(R.id.availableGoodRadio); // Initialize RadioGroups availableRadioGroup = (RadioGroup) findViewById(R.id.availableRadioGroup); // Add ChangeListener To Radio buttons addChangeListenerToRadios(); // Initialize the Spinner problemsSpinner = (Spinner) findViewById(R.id.problemsSpinner); problemsSpinner.setPrompt("Problem Solving"); // Add ItemSelectedListener To Spinner addItemSelectedListenerToSpinner(); // Initialize Buttons startChronometerButton = (Button) findViewById(R.id.startChronometerButton); pauseChronometerButton = (Button) findViewById(R.id.pauseChronometerButton); resetChronometerButton = (Button) findViewById(R.id.resetChronometerButton); // Add setOnClickListeners for buttons setButtonOnClickListeners(); // Initialize Chronometer timeWaitingChronometer = (Chronometer) findViewById(R.id.timeWaitingChronometer); // TextView for Chronometer timeWaitingTextView = (TextView) findViewById(R.id.timeWaitingTextView); // END OF NEW PART --------------- } // Called when the bill before tip amount is changed private TextWatcher billBeforeTipListener = new TextWatcher(){ @Override public void afterTextChanged(Editable arg0) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub } @Override public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { try{ // Change the billBeforeTip to the new input billBeforeTip = Double.parseDouble(arg0.toString()); } catch(NumberFormatException e){ billBeforeTip = 0.0; } updateTipAndFinalBill(); } }; // Update the tip amount and add tip to bill to // find the final bill amount private void updateTipAndFinalBill(){ // Get tip amount double tipAmount = Double.parseDouble(tipAmountET.getText().toString()); // The bill before tip amount was set in billBeforeTipListener // Get the bill plus the tip double finalBill = billBeforeTip + (billBeforeTip * tipAmount); // Set the total bill amount including the tip // Convert into a 2 decimal place String finalBillET.setText(String.format("%.02f", finalBill)); } // Called when a device changes in some way. For example, // when a keyboard is popped out, or when the device is // rotated. Used to save state information that you'd like // to be made available. @Override protected void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putDouble(TOTAL_BILL, finalBill); outState.putDouble(CURRENT_TIP, tipAmount); outState.putDouble(BILL_WITHOUT_TIP, billBeforeTip); } // SeekBar used to make a custom tip private SeekBar tipSeekBar; private OnSeekBarChangeListener tipSeekBarListener = new OnSeekBarChangeListener(){ @Override public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // Get the value set on the SeekBar tipAmount = (tipSeekBar.getProgress()) * .01; // Set tipAmountET with the value from the SeekBar tipAmountET.setText(String.format("%.02f", tipAmount)); // Update all the other EditTexts updateTipAndFinalBill(); } @Override public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } @Override public void onStopTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.crazy_tip_calc, menu); return true; } }
Hi Derek,
My dad tried to copy/paste the activity xml file but the graphical layout was screwed up.
Update:
I fixed the problem. I had to restart ecliipse 🙂 Mind you I’m using the new eclipse mod from google 🙂 Sorry 🙂
I’m glad you got it fixed 🙂 Yes, Android Studio is a bit buggy
Hey Derek, if you can, could you please find a way to get rid of the line of numbers on the side of each line, or tell me an easy way to get rid of them if I copy them into eclipse. I have tried find and replace but that messes up the code and it is very difficult to fix it.
If you drift your mouse over the upper right hand corner of the code 3 icons show up. Click on the one named view source. It will get rid of all the line numbers
Wow, thank you
You’re very welcome 🙂
Absolutely fabulous tutorial.
I imagine how hard Derek works to create a comprehensive lecture and not being drown into details that always obscure the real goal of any tutorial.
For example the case with declaring a static final variable then assigning value to it later in the code seems against the java logic and it begs to be explained.
However it would be deviation from the target – to learn how to program Android apps.
Tech details can be clarified by docs.
I would recommend to anybody do not copy/paste but write the code manually even change the names of variables to accelerate the learning process.
Thank you very much for the kind message 🙂 I’m happy that you are enjoying them. Many more videos are coming
I agree – these tutorials are wonderful. I have been doing what this comment suggests and manually building the apps, changing the variable names to suit my coding style, and looking back to Derek’s work as reference. I think it’s an amazing way to learn!
I also find that adding a few new features forces me to make mistakes and then do research on how to fix my mistakes. On my version of this app, I added a “tip amount” that displays (and allows you to edit) the amount of the tip to write in on your credit card. Making these types of simple changes helps me to understand what I’m actually doing rather than just copying the code.
Thanks again Derek for the stellar work!
Thank you very much 🙂 The nice comments I receive from people like you are the reason why I keep making tutorials.
Derek, you are so awesome. The tutorials you make are like so good. You communicate, explain everything meanwhile creating an ENTIRE app. Unlike other you explain everything to create an actual app others explain Ie only listeners or other stuff. But you learn us how to use it in an app.
I really appreciate your effort in this tutorials, I look over them, create a app and get smarter. I also have fun since I can see my result! Thank you so much. Keep on going!
Thank you for taking the time to tell me that you liked the videos 🙂 I plan on making many more Android tutorials. The only problem with them is that I have to try and make good apps that are also easy to understand. I just gave up on another today, because I couldn’t figure out how to simplify it. I promise I’ll make many more.
Derek
Thanks for the tutorial, I have a problem, when I create the start, pause and reset button the text gets cut off how do I correct it and how do I change the font size
As the tutorial continues I cover all of that. The font size is changed in the xml file with something like this android:ems=”10″
Keep going and you’ll get it. I’m covering everything in extreme detail.
can you help me..
I do not know why in the graphical layout I don’t have the emulator for that I can not add the buttons and other things like you?!!
Check out the first 2 videos in my Android Video Tutorial. Also make sure you look at Install Eclipse for Java to make sure Eclipse is properly installed.
I am just starting out though I have had many years in an education setting with Java. Eclipse is new to me… as is android anything. We always used a much simpler compiler so I just never had the opportunity to learn Eclipse. My issue is that in tutorial 3 for both bill and tip EditText I was unable to add in the Text or InputType via the properties box on the GUI. Those rows were grayed out for me and I was forced to add them in via code. Is this normal or was I doing something wrong?
Loving your tutorials! Just amazing and so helpful. Exactly what I was looking for. Thanks so much for your time and effort!
Pam
Hi Pam,
Developing for Android is most definitely different from straight Java, but once you get used to it it becomes second nature.
I learned by digging through the API a few years ago. By doing that I’d say it took me about 2 months to get comfortable with writing Android apps. I hope these videos speed up that process.
As per your error, what version of Eclipse are you using and what OS are you using? Eclipse Kepler can be a bit buggy unless you use Java 1.6 on some computers. I show how to fix that problem in my latest tutorial.
I hope that helps
Derek
Derek,
Thank you for your response. I am running win 7 64bit. Java is 7u45 and as for Eclipse I can only assume I am using Kepler. I just downloaded and started this Nov 10 and downloaded the latest versions offered. Looking at that tutorial you linked it looks as though I have to step back to 6u45 for the Java? Just did that. Will let you know if I have any more issues.
I have to say that you have made it much easier to really get into the development. I have found myself working ahead slightly and then watching your vid to catch up and check myself. You putting out the files makes it much easier as well as I do not have to type it all out. The goal is to eventually make something (sneaky) for my son to get him to play and learn at the same time. We homeschool and he is so hyper that some days I can barely get him to stop spinning in circles much less do homework! (Will give you the shirt off his back as he chases a butterfly into the highway… =)) Your tutorials have really helped me feel that this is a possibility.
Thank you so much.
Pam
Wow, I could never home school. I have no idea how you do it. My 4 and 1 year old are completely crazy. I’m very impressed by your skill as well as by your devotion 🙂
I hope to eventually start creating videos and apps that work together to teach Math, Science, etc. They will all be free just like now. I have been moving towards that goal for a while. I hope it will provide the tools needed to give a free education to all. It is a very exciting goal for me.
If you need any more help setting up Eclipse tell me. I think if you downgrade Java though that you’ll be ok.
Derek
Derek,
I worked for about 5 years at the community college I received my associates. I wore a few different, but related, hats. TA (teaching assistant), tutor, and mentor. Subjects taught were computer science / math / language arts and college admission. I also worked as a tutor for the university I was attending for my (unfinished) BS – Computer Science. I had students come into the tutoring center (young* enough to be a grandparent of mine and teenagers having JUST graduated high school) that had difficulty adding and subtracting. Yes… these high schoolers couldn’t add yet had just graduated high school…. gotta love Texas education system. =( Wonder why I have chosen to home school???
This just tore me up. It is discouraging to see all the difficulty these wonderful people had with (what I considered) simple math or writing. I decided then and there that one day I would come up with some program that was interactive, simple, and fun. One that would work for ages 3-103. Whatever it took, to develop a way for people to get the help they need for math. It is a dream of mine. I have searched high and low for the platform to do it… and well… the time.
My kids are 9 and 11. After homeschooling them and everyday life it is difficult to find time. I can get done in one night what would take me a full week working with the code. If you are able to accomplish this before I can then heck yeah! I will scream it loud and often to these poor students. Anything to help them. I have seen some awesome, amazing people completely give up on their dreams because the concept of fractions stood in their way. I don’t have a ton of experience but I am a quick study and am a hard worker. If there is anything I can do to help YOU get to helping people education wise more quickly… just drop me an email and I will do what I can.
Pam
Thank you very much for sharing. Like you I’m pretty disgusted by the education system. I don’t blame teachers, but instead I blame the general system. The schools near my house are terrible as well.
I’m not big on trying to solve problems through political channels so instead I do hope to make a ton of educational apps. I will probably work the rest of my life trying to make them better and better. I don’t think they’ll ever be perfect, but I think they’ll help some people and that is good enough for me.
Hopefully along the way I can make this whole programming thing easier as well. That way more people will be able to join in. I haven’t by any means perfected this area of teaching yet, but I’m getting better each time. I plan on covering Android for quite some time. I will also eventually start over from the beginning and improve on this tutorial.
Thank you for offering to help. It may sound strange, but just knowing that there are people out there that enjoy these videos is enough for me. Always feel free to tell me where I can improve. I need some negative comments as well 🙂
Thanks
Derek
As you said, you wanted some negative comments to improve yourself. So there is some: You are speaking so quick and sometimes it is a little bit obscure mostly for no native speakers as me. It is hard to pay attantion to understanding speech and the content at the same time. But this is very subjective i think.
Yes I agree that I need to find a better pace and I’m working on that in every video. Thank you for the input 🙂
Hi Derek, thank you very much for your videos. I have been so bored from webdeveloping and stuffs around web and this is a big opportunity for me to learn something new. The way you are teaching is more powerfull then reading book about android developing which i have. Realy good job.
Sorry for my english, im not native speaker.
Hi Martin,
Thank you I’m doing my best to teach Android development in a new way. I’m enjoying these videos so much that I plan to make them for many more months.
Your English is very good as well. Thanks for taking the time to say hi 🙂
HI Derek,
I have a one question. timeWaitingTextView is not being utilized or used anywhere in .java file. However, is that required to initialize it as we have done in statement
timeWaitingTextView = (TextView)findViewById(R.id.timeWaitingTextView);
Thanks in advance. I am really learning fast just because of your elaborative tutorials 🙂
Hi Kuldeep, As the tutorial continues I use timeWaitingTextView.
Derek you can’t believe how much I am thankfull for this tutorials you are the only one that actually explain everything and show your own apps
Basiclly I want to say a giant thanks and I am going to publish my own app with all those stuff I learnt from this “course”
Thank you 🙂 I’m very happy that you are enjoying them. I’ll keep making Android apps until anyone that wants to can learn to make most anything. They are great fun to make and quite profitable.
Hi derek i really love your tutorials. just wanted to find out if there is any particular tutorials showing how an app communicates over the internet. yeah i know it sounds strange am actually working on a final year project please help
Thank you 🙂 I do cover how to read data from a yahoo web service. That tutorial starts here. I will show how to create web services soon with PHP.
I just want to say that this is by far the best Android tutorial series I’ve seen anywhere.
You sir are really knowledgable and I appreciate very much you are taking the time to help the rest of us learn.
Schools really became a business nowadays and don’t provide that good of an education (at least from my perspective as a student at UM).
I’m hoping to start one of these educational websites myself eventually for my own country/language.
Once again, thank you and big thumbs up 🙂
Thank you for the very nice compliment 🙂 I always treated my website as if it was a type of trade school. Especially in the last 2 years I aimed to teach people exactly what they need to know to go off on their own. I wish I could better simulate in person teaching and I think I’ll get there some day.
Amazing tutorials!!!
Great flow…professional and friendly.
Your tone of voice makes me feel calm, as if i can learn everything- no panic.
thanks man.
Thank you very much 🙂 I’m glad you enjoy the videos.
Hello Derek,
your tutorials are very good and I understood a lot of things so far. And I really appreciate for that.
But I have a problem with Java. If you compare it to C or similar programming languages, Java is so weird.
There are so many identifiers and I didn’t figured out yet how I have to use them and so it is very complicated to follow all of your code.
Do you know a good Java tutorial where I can learn it?
Thank you in advance 😉
and by the way:
Where I can find the OnClickListeners for the three buttons?
It is invoked but I can’t find the declaration.
Oh I am sorry, I got it, it is in the next tutorial 😀
I’m glad you found it. Sometimes it takes a couple videos to cover everything.
Hello,
I made a Java tutorial that you may like.
Good tutorial, you have bug in this code though
when tip is updated with slidebar and than when you go back and enter new tip in text editor it does not work
here is my code with a fix for it:
package com.goxoft.crazytipcalc;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.os.Build;
public class CrazyTipCalc extends Activity {
private static final String TOTAL_BILL = “TOTAL_BILL”;
private static final String CURRENT_TIP = “CURRENT_TIP”;
private static final String BILL_WITHOUT_TIP = “BILL_WITHOUT_TIP”;
private double billBeforeTip;
private double tipAmount;
private double finalBill;
EditText billBeforeTipET;
EditText tipAmountET;
EditText finalBillET;
SeekBar tipSeekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crazy_tip_calc);
if(savedInstanceState==null){
billBeforeTip = 0.0;
tipAmount = 0.15;
finalBill = 0.0;
} else {
billBeforeTip = savedInstanceState.getDouble(BILL_WITHOUT_TIP);
tipAmount = savedInstanceState.getDouble(CURRENT_TIP);
finalBill = savedInstanceState.getDouble(TOTAL_BILL);
}
billBeforeTipET = (EditText) findViewById(R.id.billEditText);
tipAmountET = (EditText) findViewById(R.id.tipEditText);
finalBillET = (EditText) findViewById(R.id.finalBillEditText);
tipSeekBar = (SeekBar) findViewById(R.id.changeTipSeekBar);
billBeforeTipET.addTextChangedListener(billBeforeTipListener);
/* tipEditText not updating bug
* ********************************************************************
*/
// this line here calls tipEditTextListener which checks if tip edit thext bar have changed
tipAmountET.addTextChangedListener(tipEditTextListener);
/***********************************************************************/
tipSeekBar.setOnSeekBarChangeListener(tipSeekBarListener);
}
private TextWatcher billBeforeTipListener = new TextWatcher(){
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
try {
billBeforeTip = Double.parseDouble(s.toString());
} catch (NumberFormatException e){
billBeforeTip = 0.0;
}
updateTipAndFinalBill();
}
@Override
public void afterTextChanged(Editable s) {
}
};
/* tipEditText not updating bug
* ********************************************************************
*/
private TextWatcher tipEditTextListener = new TextWatcher(){
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// This guy updates a tip anytime it have changed */
try {
tipAmount = Double.parseDouble(s.toString());
} catch (NumberFormatException e) {
tipAmount = 2.0;
}
// Updates seek bar after tipEditText have been changed
tipSeekBar.setProgress((int) (tipAmount*100));
// call to our update method
updateTipAndFinalBill();
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
};
private OnSeekBarChangeListener tipSeekBarListener = new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
tipAmount = tipSeekBar.getProgress()*0.01;
tipAmountET.setText(String.format(“%.2f”, tipAmount));
updateTipAndFinalBill();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
};
private void updateTipAndFinalBill() {
double tipAmmount = Double.parseDouble(tipAmountET.getText().toString());
double finalBill = billBeforeTip + (billBeforeTip*tipAmmount);
finalBillET.setText(String.format(“%.2f”, finalBill));
}
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
outState.putDouble(BILL_WITHOUT_TIP, billBeforeTip);
outState.putDouble(CURRENT_TIP, tipAmount);
outState.putDouble(TOTAL_BILL, finalBill);
}
}
Thank you 🙂 Sorry about not setting up that feature in the code. I was writing this out of my head.