We start a new application in this lab, which will be succeeded by numerous version over the next few topics. In this lab the focus is on explaining the essential 'plumbing' of the app, and introducing the first Interface based listener you may have encountered.
Complete the New Android Application Wizard as shown in the following screenshots (Figure 4):
When the Finish button is pressed, the result is as displayed in Figure 5
The directory structure, viewable in Eclipse Package Explorer, is depicted in Figure 6.
Some of the key files of the application are identified in the screenshot of the Package Explorer as illustrated in Figure 1.
Layout XML Code
The file activity_myrent.xml specifies the screen layout. The textual content of the file is as follows:
<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="org.wit.myrent.MyRentActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
This translates to the graphical layout shown in Figure 2.
Tabs enable one to quickly switch between graphical and textual content as demonstrated in Figure 3.
From the XML above you can see that the layout comprises a TextView wrapped in a Relative Layout.
A Relative Layout is a parent container for views, referred to as child views, that are arranged in relative positions to each other. In this app, to date, there is only one child view - a TextView.
A TextView displays text and is configured by default to be read-only.
Both the RelativeLayout and TextView definitions contain attributes that determine characteristices such as, for example, their size and position.
Thus, in the case of TextView, the attribute android:layout_width, whose value is wrap_content, determines that the view will be created just wide enough to contain the text specified by the attribute android:text (whose value is @string/hello_world).
This becomes clear if you select Hello world in the graphical representation of activity_myrent.xml as demonstrated in Figure 4.
Were the TextView attribute android:layout_width set to fill_parent the situation would be as represented in Figure 5.
A short tutorial is available is available here that demonstrates the effect of different values for layout_width and layout_height attributes.
The file strings.xml, located in res/values, contains all the text that MyRent application uses. This arrangement, rather than hard-coding strings when and where required in the code, greatly facilites any changes to the strings, such as for example adapting your application to a new language.
Presently strings.xml contains only 3 entries (see Figure 1):
At any location in the code that the name of the application is required it may be obtained by accessing a string element thus:
"@string/app_name"
This is illustrated in Figure 3 below where the application's name is retrieved in AndroidManifest.xml.
Figure 4 shows how the Hello world! string, displayed when the application is launched, is obtained.
Figure 5 shows how an entry in the Action bar (Settings) is obtained.
All auto-generated files are located in the gen folder and should not be modified by the developer.
MyRentActivity
onCreate
onCreateOptions
onOptionsItemSelected
Start the Genymotion emulator
Run the app
Select myrent-android project in the Eclipse Package Explorer
We first begin with a new model class: Residence.
package org.wit.myrent;
import java.util.UUID;
public class Residence
{
private UUID id;
//a latitude longitude pair
//example "52.4566,-6.5444"
private String geolocation;
public Residence()
{
id = UUID.randomUUID();
}
public void setGeolocation(String geolocation)
{
this.geolocation = geolocation;
}
public String getGeolocation()
{
return geolocation;
}
}
A general note on layout development: Android Development Kit (ADK) provides two ways to to create a user interface (UI):
Declarative
Programmatic
In this series of labs we shall develop the UI in XML but use Java to where necessary to interact with UI components. For example when data is entered in a UI control (for example a text input component), then the ensuing operations will be handled programmatically using Java.
Back to the present iteration: We have completed the refactoring of the Java code.
Here we shall address the necessary changes to the layout.
First, we need to make a change to the file res/values/strings.xml.
The legacy code from the baseline MyRent app is as shown here in Figure 1:
Replace this with the following:
Filename: strings.xml
<resources>
<string name="app_name">MyRent</string>
<string name="title_activity_myrent">MyRentActivity</string>
<string name="geolocation_hint">52.253456,-7.187162</string>
<string name="action_settings">Settings</string>
</resources>
Observe that we have deleted the Hello world! string and replaced it with a string describing the Geolocation hint.
Recall the output generated on launching the baseline app:
Our goal is now to replace this output with the following:
Open activity_myrent.xml in the folder res/layout
Its content should be as shown in Figure 4:
Replace the content of the file with the following:
<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="org.wit.myrent.MyRentActivity" >
<EditText
android:id="@+id/geolocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:hint="@string/geolocation_hint" />
</RelativeLayout>
.
Study the Graphical Layout, Outline and Properties in the IDE, all as shown in Figure 5.
The application should be error free and capable of being launched and generating output as shown here in Figure 6.
Tip: in order to understand more clearly how layout works, refer to Figure 7 below which shows how selected parts of the UI may be colored during development.
Filename: colors.xml
<resources>
<color name="red">#ffff0000</color>
<color name="green">#FF99CC00</color>
<color name="blue">#FF33B5E5</color>
<color name="orange">#FFFFBB33</color>
<color name="purple">#FFAA66CC</color>
<color name="darkorange">#FFFF8800</color>
</resources>
We shall now inject code into the MyRentActivity class that shall:
Here are the steps in refactoring MyRentActivity to introduce a listener:
First introduce a reference to the model object + the TextEdit field:
public class MyRentActivity extends Activity
{
private EditText geolocation;
private Residence residence;
import android.text.Editable;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_myrent);
geolocation = (EditText) findViewById(R.id.geolocation);
residence = new Residence();
}
Next we implement the Listener interface:
public class MyRentActivity extends Activity implements TextWatcher
{
This will generate errors until we provide a suitable implementation:
@Override
public void afterTextChanged(Editable c)
{
residence.setGeolocation(c.toString());
}
@Override
public void beforeTextChanged(CharSequence c, int start, int count, int after)
{
}
@Override
public void onTextChanged(CharSequence c, int start, int count, int after)
{
}
These imports are required:
import android.text.Editable;
import android.text.TextWatcher;
Let's examine the listener code in some detail. This is contained in the method private void geolocation.
Note that we have created an instance variable EditText geolocation.
The statement geolocation = (EditText) v.findViewById(R.id.geolocation); obtains a reference to the Geolocation input contol and assigns it to this instance variable.
EditText is a subclass of TextView. TextView has a method addTextChangedListener. We invoke this method.
Here is what we have done in this topic:
Created a model class, Residence.
Created a layout in xml
Added a listener to the Activity class to capture any changes in input (the geolocation) and transmit these changes to the Residence object for storage.