Getting Started with Android Development

Note from Ray: Although this site has been focused on iOS development so far, I thought you guys might enjoy learning a bit about Android development as well. So iOS tutorial team member Ali Hafizji has put together this great tutorial on Android development for beginners! I had never programmed for Android before, but bought […] By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Creating a Simple and Easy App

The current state of the application is quite raw and we haven’t yet added anything to the default project. So lets try and build something small but useful.

In this part of the tutorial we will build a tiny application. The idea is to build a quote reader. The quotes will be displayed in a list and when the user clicks on an item the app will navigate to a detailed page containing a picture and the quote.

The first screen contains a list with quotes and thumbnails. Lets start by creating the UI for this.

Step 1: Adding the list view

If you’re coming from the iOS development world, you’re familiar with using Interface Builder to graphically layout an interface. However, because Android supports so many different devices with different screen sizes, creating user interfaces is completely different.

Instead of visually dragging and dropping UI elements to a canvas, you need to define your UI in XML (yes, you read that right!). You’ll add XML tags for the views you want (like buttons, labels, etc.) and add XML attributes for parameters like position, color, etc.

Eclipse does come with a visual editor where you can drag drop UI elements, but I highly recommend editing the XML directly instead as this will give you a stronger grip over your view hierarchy.

In this tutorial, we’ll show you exactly what to input in the XML to set up the UI, but if you want to read about how it all works, check out Android’s XML layout guide here.

Now lets open the main.xml file from the res/layout directory. If the graphical layout view appears, select the main.xml tab to edit raw xml. Then replace the content with the following:

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/quotes_list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
</ListView>

This will create a list view with a width and height equal to the size of the screen.

Next we need to show this layout to the user, to do this open QuoteReaderActivity.java present in the source directory. You will notice that this class extends a class named Activity. In Android anything that the user interacts with is an activity, the activity is responsible for showing the user content which is present in different views.

Notice that a method called onCreate is overridden and in it a method called setContentView is called. This sets the content of this activity with views present in the xml file passed to it.

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

The “R” class present above is used to refer to the resources present in the /res folder. Here’s a screenshot of the contents of this folder of this project:

Resources automatically compiled into R class

The “R” class is automatically generated to contain properties for the resources that you put into this folder. For each type of resource, there is an “R” property (for example R.layout for all the layout resources) and for each resource of that type there is a static integer (for example R.layout.main). This integer is the resource ID that you can use to retrive that resource.

This is the xml file in which we just added the list view. Hence when the QuoteReader activity is started it will create our list view.

Go ahead and run your application you should see a blank screen. This is because we haven’t yet added any rows to our list view.

Step 2: Adding rows to the list

In this step we will create rows and add them to our list. We know that the row needs to have a thumbnail and text.

Here is how the row is going to look:

Lets start by creating the layout for the row. Create a new xml file in the res/layout directory and name it “list_item_layout.xml”. Open it in the raw XML view and replace the contents with the following:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="100dip" >
    <ImageView 
        android:id="@+list/thumb"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        />
    <TextView
        android:id="@+list/text"
        android:layout_toRightOf="@+list/thumb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18dip"
        android:layout_marginLeft="10dip"
        android:layout_centerVertical="true"
        android:singleLine="true"
        android:ellipsize="end"
        android:textStyle="bold" 
        />
</RelativeLayout>

This creates an ImageView for the thumbnail and a TextView for the quote.

Note that we give the ImageView and TextView an ID. An ID is used to uniquely identify a view within a view hierarchy. The syntax is funky here so let’s explain it bit by bit:

  • The at-symbol(@): You put this at the beginning, and it indicates that the XML parser should parse and expand the rest of the ID string and identify it as an ID resource.
  • The plus-symbol(+): This means that this is a new resource name and that must be created and added to our resources.
  • How to use: After the app is compiled you will be able to refer to this view using “R.list.text”.

Notice that the parent view used in this layout is a RelativeLayout. This layout allows you to position its children relative to each other and itself. The ImageView needs to be placed to the left of the layout and it needs to be centered vertically hence those properties are set to true. Also the TextView needs to contain text in a single line and if the length increases it should ellipsize, therefore the single line and ellipsize properties are set.

Now that we have the UI in place, lets add some code so that we can use it for each list item.

Step 3: Understanding adapters and data sources

Okay lets take a brief pause and let me try and explain how a list view is populated with data. Data is present in something known as a data source this is the object that provides the data that will populate the list view. This is usually just a subclass of NSObject – think of it as your app’s model.

An adapter sits between the data source and the list view. It provides the list with data from the data source and refreshes the list items when a scroll occurs.

Android has two standard adapters, ArrayAdapter and CursorAdapter. You can also develop your own adapter by extending these classes or the BaseAdapter class. We will be extending the BaseAdapter class later on in this tutorial, but let’s create the data source first.

Step 4: Creating the data source

First copy all the images that are provided here in your drawable directory. If you don’t have a drawable directory, go ahead and create it. The drawable directory basically should contains items that can be drawn to the screen. The resources that you place here can be referenced through the “R” class. For example “R.drawable.icon” would refer a resource name icon in the drawable folder.

Next, download the quotes we’ll be using for the project and add them into your res/values/strings.xml file. The reason why I added strings to an xml file and not use them directly in code is because I like to keep my resources separate, also this helps a lot when you’re localizing strings. Again you can refer the strings placed here using the same “R” class, for example “R.string.quote_1” would refer the quote_1 string.

Add the quotes to the file according to the following syntax:

<string name="quote_1">Innovation distinguished between a leader and a follower</string>
<string name="quote_2">I want to put a ding in the universe!</string>
<string name="quote_3">People don\'t know what they want until you show it to them.</string>
<!--  add rest of quotes, up to quote_10  -->

Notice that you have to precede any single quotes with a backslash.

Now that we have all the data, lets create our data source class. Right click on your src folder goto New and select Class. Name it DataSource, make sure the Package is set to whatever package QuoteReaderActivity.java is part of, and press finish. Add the following lines of code to it:

	
private ArrayList<Integer> mPhotoPool;
private ArrayList<Integer> mQuotePool;
private ArrayList<Integer> mPhotoHdPool;

public ArrayList<Integer> getmPhotoHdPool() {
    return mPhotoHdPool;
}

public ArrayList<Integer> getmPhotoPool() {
    return mPhotoPool;
}

public ArrayList<Integer> getmQuotePool() {
    return mQuotePool;
}

public DataSource() {
    mPhotoPool = new ArrayList();
    mQuotePool = new ArrayList();
    mPhotoHdPool = new ArrayList();
}

All that we have done here is create 3 variables, generated their getter methods, and initialized the variables in the constructor.

If you get warnings that it can’t find ArrayList, simply go to Source\Organize Imports to have Eclipse automatically add the import you need to the top of the file. You can do this same thing whenever you get warnings on missing imports later on in this tutorial as well.

Next we need to populate the array lists with our data, which are the pictures and the quotes. Notice that we have defined our array list to contain integers. The reason for this is when you drop any resource into the resource directory the build system creates a unique identifier for it which is represented by an integer.

Okay now lets create 3 separate functions to populate our ArrayLists. Add the following functions above the constructor definition.

private void setupPhotoPool() {
	mPhotoPool.add(R.drawable.steve_1);
	mPhotoPool.add(R.drawable.steve_2);
	mPhotoPool.add(R.drawable.steve_3);
	mPhotoPool.add(R.drawable.steve_4);
	mPhotoPool.add(R.drawable.steve_5);
	mPhotoPool.add(R.drawable.steve_6);
	mPhotoPool.add(R.drawable.steve_7);
	mPhotoPool.add(R.drawable.steve_8);
	mPhotoPool.add(R.drawable.steve_9);
	mPhotoPool.add(R.drawable.steve_10);
}

private void setupQuotePool() {
	mQuotePool.add(R.string.quote_1);
	mQuotePool.add(R.string.quote_2);
	mQuotePool.add(R.string.quote_3);
	mQuotePool.add(R.string.quote_4);
	mQuotePool.add(R.string.quote_5);
	mQuotePool.add(R.string.quote_6);
	mQuotePool.add(R.string.quote_7);
	mQuotePool.add(R.string.quote_8);
	mQuotePool.add(R.string.quote_9);
	mQuotePool.add(R.string.quote_10);
}

private void setupPhotoHDPool() {
	mPhotoHdPool.add(R.drawable.steve_hd_1);
	mPhotoHdPool.add(R.drawable.steve_hd_2);
	mPhotoHdPool.add(R.drawable.steve_hd_3);
	mPhotoHdPool.add(R.drawable.steve_hd_4);
	mPhotoHdPool.add(R.drawable.steve_hd_5);
	mPhotoHdPool.add(R.drawable.steve_hd_6);
	mPhotoHdPool.add(R.drawable.steve_hd_7);
	mPhotoHdPool.add(R.drawable.steve_hd_8);
	mPhotoHdPool.add(R.drawable.steve_hd_9);
	mPhotoHdPool.add(R.drawable.apple_hd);
}

Each of these functions is filling in data into our ArrayLists. Call these functions in the constructor like so:

setupPhotoPool();
setupQuotePool();
setupPhotoHDPool();

We will also add another function for the size of the data source. In our case the size of the data source is 10 i.e. we have 10 images and 10 quotes hence we can simply return the size of any one of our ArrayLists.

Add the following function above the constructor:

public int getDataSourceLength() {
	return mPhotoPool.size();
}

That’s all we need. Next we need to use this data source and populate our list.

Step 5: Creating the adapter

Open QuoteReaderActivity.java from the src folder and create a private class, name it QuoteAdapter. This class should inherit from the BaseAdapter class and it should implement all the abstract methods with minimal implementations.

Here’s what the class should look like now:

public class QuoteReaderActivity extends Activity {

    public class QuoteAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return 0;
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            return 0;
        }

        @Override
        public View getView(int arg0, View arg1, ViewGroup arg2) {
            return null;
        }
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

Lets try and understand what each method does.

  • getCount(): Returns the number of items present in the data set.
  • getItem(int position): Gets the data item associated with the specified position in the data set.
  • getItemId(int position): Gets the row id associated with the specified position.
  • getView( int position, View convertView, ViewGroup parent): This is used to get a view that displays the data at the specified position in the data set.

Now that we have a basic understanding of all the functions lets add a constructor to our adapter and some private variables. Add the following lines of code to the QuoteAdapter class:

private Context mContext;
private LayoutInflater mInflator;
private DataSource mDataSource;

public QuoteAdapter(Context c) {
        mContext = c;
        mInflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mDataSource = new DataSource();
}

The only new variable here is the mInflator variable this is used to instantiate layout XML file into its corresponding View objects.

Next change all the overridden functions as follows:

@Override
public int getCount() {
	return mDataSource.getDataSourceLength();
}

@Override
public Object getItem(int position) {
	return position;
}

@Override
public long getItemId(int position) {
	return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
	ImageView thumbnail;
	TextView quote;
	
        if(convertView == null) {
		convertView = mInflator.inflate(R.layout.list_item_layout, parent, false);
	}

	thumbnail = (ImageView) convertView.findViewById(R.list.thumb);
	thumbnail.setImageResource(mDataSource.getmPhotoPool().get(position));
	quote = (TextView) convertView.findViewById(R.list.text);
	quote.setText(mDataSource.getmQuotePool().get(position));
	return convertView;
}

The main function here is the getView function, since it is called for every item in the list view. It is responsible for binding the data source with the list view item.

In it we first check if the convert view is null, the reason we do this is to check if the convertView returned is not a recycled view. The adapter does not create a new view for each and every item instead it creates a set number of views and reuses them as the users scrolls through the list. This is similar to how a UITableView reuses table view cells in iOS.

Once this is done we get a reference to our image view and text view and fill it with data from our data source. The position variable returned is used as an index in the data source.

Step 6: Getting things together

We now have our adapter and data source set we just need to tell our list view to start using our adapter. Add the following private variable to QuoteReaderActivity:

private ListView mListView;

Then add the following lines in the onCreate method:

 
mListView = (ListView) findViewById(R.id.quotes_list);
mListView.setAdapter(new QuoteAdapter(this));

That’s it! Now run the application, and you should see a screen like this:

Congrats! You have made a simple Android app that shows thumbnails of the famous Steve Jobs and his most famous quotes.

Contributors

Over 300 content creators. Join our team.