Examining Tipster.java

Next we look at the Tipster.java file which controls our application. This is the main class which does the layout, the event handling and the application logic.

Application code - Tipster.java

The Android Eclipse plugin creates the Tipster.java file in our project with default code as follows -

Open code in a window

The Tipster class extends the android.app.Activity class. An activity is a single, focused thing that the user can do. The Activity class takes care of creating the window and then laying out the UI. You have to call the setContentView(View view) method to put your UI in the Activity. So think of Activity as a outer frame which is empty, and you populate it with your UI.

Now look at the snippet of the Tipster.java class. First we define the widgets as class members. Look at lines 3 to 12 of the code snippet 2 below for reference.

Then we use the findViewById(int id) method to locate the widgets. The ID of each widget, defined in your main.xml file, is automatically defined in the R.java file when you clean and build the project in Eclipse. (If you have set up Eclipse to Build Automatically, then the R.java file is instantaneously updated when you update main.xml)

Each widget is derived from the View class, and provides special graphical user interface features. So a TextView provides a way to put labels on the UI, while the EditText provides a text field.  Look at lines 24 to 41 in the code snippet 2 below. You can see how findViewById() is used to locate the widgets.

Open code in a window

 

Addressing 'ease of use' or Usability concerns

Our application must try to be as usable as any other established application or web page. In short, adding Usability features will give a good user experience. To address these concerns look at the code snippet 2 again.

Look at line 26 where we use the method requestFocus() of the View class. Since EditText widget is derived from the View class, this method is applicable to it. This is done to so that when our application loads, the 'Total Amount' text field will receive focus and the cursor will be placed in it. This is similar to popular web application login screens where the cursor is present in the username textfield.

Now look at line 35 where the 'Calculate' button is disabled by calling the setEnabled(boolean enabled) method on the Button widget. This is done so that the user cannot click on it before entering values in the required fields. If we allowed the user to click Calculate without entering values in the 'Total Amount' and 'No. of People' fields, then we would have to write validation code to catch these conditions. This would entail showing an alert popup warning the user about the empty values. This adds unnecessary code and user interaction. When the user sees the 'Calculate' button disabled, its quite obvious that unless all values are entered, the tip cannot be calculated.

Look at line 44 in the code snippet 2. Here the 'Other Percentage' text field is disabled. This is done because the '15% tip' radio button is selected by default when the application loads. This default selection on application load is done via the main.xml file. Click here to go to main.xml and then look at line 66, where the following statement selects the '15% tip' radio button.

android:checkedButton="@+id/radioFifteen"

The RadioGroup attribute android:checkedButton allows you to select one of the RadioButton widgets in the group by default.

Most users, who have used popular applications on the desktop as well as the web, are familiar with the 'disabled widgets enabled on certain conditions' paradigm..

Adding such small conveniences always makes the application more usable and the user experience richer.

 

Processing UI events

Like popular Windows, Java Swing, FLex, etc. UI frameworks, Android too provides an Event model which allows to listen to certain events in the UI caused by user interaction. Let us see how we can use the Android event model in our application.

Listening to radio buttons

First let us focus on the radio buttons in the UI. We want to know which radio button was selected by the user, as this will allow us to determine the 'Tip Percentage' in our calculations. To 'listen' to radio buttons, we use the static interface OnCheckedChangeListener(). This will notify us when the selection state of a radio button changes.

In our application, we want to enable the 'Other Tip' text field only when the 'Other' radio button is selected. When the 15% and 20% buttons are selected we want to disable this text field. Besides this, we want to add some more logic for sake of usability. As discussed before, we should not enable the 'Calculate' button till all required fields have valid values. In case of the three radio buttons, we want to ensure that the Calculate button gets enabled for the following two conditions -

  • Other radio button is selected and the 'Other Tip Percentage' text field has valid values
  • 15% or 20% radio button is selected and 'Total Amount' and 'No. Of People' text fields have valid values.

Look at the code snippet 3 which deals with the radio buttons. The source code comments are quite self explanatory.

Open code in a window

 

Monitoring key activity in text fields

As I mentioned earlier, the 'Calculate' button must not be enabled unless the text fields have valid values. So we have to ensure that the Calculate button will be enabled only if the 'Total Amount', 'No. of People' and 'Other' tip percentage text fields have valid values. The Other tip percentage text field is enabled only if the Other Tip Percentage radio button is selected. 

We do not have to worry about the type of values, i.e. whether user entered negative values or alphabetical characters because the android:numeric attribute has been defined for the text fields, thus limiting the types of values that the user can enter. We have to just ensure that the values are present.

So we use the static interface OnKeyListener(). This will notify us when a key is pressed. The notification reaches us before the actual key pressed is sent to the EditText widget. 

Look at the code snippet 4 and 5 which deals with key events in the text fields. 

The source code comments are quite self explanatory.

Open code in a window

Notice that we create just one listener instead of creating anonymous/inner listeners for each textfield. I am not sure if my style is better or recommended, but I always write it in this style if the listeners are going to perform some common actions. Here the common concern for all the text fields is that they should not be empty, and only when they have values should the Calculate button be enabled.

Open code in a window

In line 18 of code snippet 5, we examine the ID of the View. Remember that each widget has a unique ID as we define it in the main,xml file. These values are then defined in the generated R.java class.

In line 19 and 20, if the key event occured in the Total Amount or No. of People fields then we check for the value entered in these fields. We are ensuring that the user has not left the fields blank.

In line 24 we check if the user has selected Other radio button, then we ensure that the Other text field is not empty. We also check once again if the Total Amount and No. of People fields are empty.

So the purpose of our KeyListener is now clear - ensure that all text fields are not empty and only then enable the Calculate button.

 

 

« 1 2 3 »