Tutorial 1 – A Simple Stopwatch (Designing & Layout)

After much consideration I decided that my first app would be a simple stopwatch app. Why? Because the stock version of Android does not have one, and it seems like something simple enough to begin with, although this may not have been the smartest move as a search for stopwatch at the time resulted in approximately 880 hits, now a search results in 1,238 hits, so it seems everyone had the same idea. Although this app will not make you a millionaire it has helped me understand some important aspects of Android that you would only come across by actually doing some coding.

Shameless Plug to my app: https://market.android.com/details?id=com.shawnbe.droidwatch

Let’s begin. The tutorial will be broken into four parts; this part will deal with setting up the general layout of the stopwatch and setting up the basic project. Over the four tutorials we will look at the sketch of the stopwatch, the use of nine patch images layout out the elements in the XML file, using custom fonts, button states , integrating ads and much more. (The stopwatch design was done in Illustrator but since this is not a design blog, nor am I a designer that process will not be covered at this time, but I will provide the resources for you to use if you wish to follow along, if there is a demand for the Illustrator tutorial I will include it in a later blog).

I am going to assume you have some basic knowledge on setting up the Eclipse development environment and you have already created the standard “Hello World” application. If however this is your first shot at building an application, I am fairly certain you will still be able to follow along and complete this tutorial. Feel free to email me if you come across any problems and I will do my best to assist you.

 

Step 1. Sketching an Initial Design.

(Disclaimer: I am not a designer, I am a developer so please forgive me if my layouts and designs break the rules and conventions of proper design) After some research, I decided to keep it simple and came up with the sketch below.

Initial Sketch

It’s a simple and functional layout, the time is displayed in a big easy to read font size which is useful for someone using it for exercising and the buttons are also large and easy to press.

In order to keep the design clean and simple, the stop button will be hidden until the start button is pressed at which time the stop button will appear in its place. At the bottom of the screen there is also a designated area to display ads (not show in this sketch can be seen below in the final design). Mobile ads seem to be the most popular model to monetize your apps and I will be covering this in a later tutorial.

 

Step 2. Start Drawing the design.

Let me reiterate, I am not a designer but I do have a little knowledge of how to use Adobe Illustrator which I use to create my designs. I am fairly certain everything  done here can be done using other software such as Photoshop or even the free software such as Inkscape and Gimp. I will not be covering the step by step process to reproduce the design, but I will include the files needed to complete the XML Layout if you wish to follow along. If there is a demand for that Tutorial it can be added later on.

When designing for Android I usually design certain items using three different artboards to represent the different pixel densities that are most common. The three main sizes I use are

  • LDPI – 240 x 400
  • MDPI – 320 x 480
  • HDPI – 480 x 800

The screen resolutions may be different than those outlined above but I use these as they are the most common. Not all items needs to be designed at the different resolutions as nine patch solves some of these issues, but certain items such as screen icons look much better when they are displayed at their native designed resolution rather than being stretched or shrunk to fit the screen.

So the final layout I came up with? It’s not the best design but I don’t think it’s too bad for a developer. For these tutorials I chose to use an actual design rather than the generic Android controls as there are many tutorials out there using the default controls Buttons, Text Views, Spinners etc and I found that using these custom designed buttons and other widget objects adds a bit more complexity that is not usually covered in most tutorials.

 

 

 

 

 

Step 3 : Almost ready to start coding.

Before I begin coding and I like to consider exactly how I am going to convert my design into a working Android Layout using the various Layout formats provided by Android. Below is the breakdown of the layouts I will be using to place the various images on the screen. Looks a bit complicated I know but, I will explain it as I go along creating the XML Layout.

 

 

Step 4 : Preparing the Images for Use (A patch in nine saves time)

A Ninepatch drawable resource is a stretchable bitmap image that automatically re-sizes to accommodate content within the view. The great thing about using the Android nine patch tool is that it lets you specify what areas of your image are stretchable and what areas are not.  This becomes very useful for example with buttons with rounded corners, if the button needs to stretch to hold more text or a larger font size you would want the straight edges of the button to stretch, however you would not want the rounded corners of the buttons to also stretch as your buttons will look distorted and misshapen.

More details on Nine Patch

http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
http://developer.android.com/guide/developing/tools/draw9patch.html

 

Let’s look at an example of using the nine patch tool on a button.

To launch the nine patch tool navigate to your Android SDK > tools folder. In my case it is located at C:\Program Files (x86)\Android\Android-SDK\tools.

Your location may vary depending on where you chose to install your SDK files initially. Once at that tools folder launch the draw9patch.bat file.

You should see a new window like the one below

 

 

File > Open9Patch and Select the image you would like to convert to a ninepatch. In my case I will be using the start button Image.

Once the Image opens you may or may not notice there is a 1 pixel wide transparent border around your image. If you hover over the middle of the image you will notice a dark gray and red diagonal pattern over the image except for the very extreme ends. As you move your cursor to the very end of the image you will notice the pattern has now disappeared and there is now a small black square at the tip of your pointer. The transparent 1 pixel border at the top and the left of your image allows you select the areas of the image are stretchable, and the bottom and right borders allow you to select where on the image content may be placed. Using your mouse go to the very edges over the transparent border and  hold down the mouse button to select pixels on this border. The selected pixels will be marked with a black line.

 

 

 

The black lines around the edge of the image above shows the areas selected as stretchable. Because I do not want the rounded edges to stretch you can see I did not select those pixels in the left and the bottom margins, also you should note that as you select pixels on the image int the left column, the right column dynamically adjusts to show how the image would look if it were stretched horizontally and vertically. You would also notice that pixels on the right and the bottom margins were selected, this allows you to specify where you want content to appear on the image. The shaded areas in the right column displays where content can appear (as seen in image below), I do not want text on the button appearing at the very edges of the button, only in the middle therefore only the pixels at the center on the bottom and right margins were selected.

If you do not see the shaded area, make sure the Show content checkbox at the bottom of the ninepatch window is selected.

 

 

You should experiment with marking different pixels and observe how the image on the right hand side is affected. Once you get the hang of it, it becomes very easy. I need to do this for all the stretchable images which are all the buttons as well as blue timer background (Image Below)

 

 

 

Step 5 : Lets write some XML

This tutorial assumes that you already have the Eclipse development environment setup with the required Android plugins. If you do not have this setup you can follow the instructions at this link to Android Developer Website  and continue along when you are finished setting up.

Open your installation of Eclipse then Create a new Android Project by navigating to

File > New Project > Android Project

 

 

 

A New Android Project Window should now appear and you should fill in the relevant information.

 

 

I have used the following to create my new project but you can change yours as required

  • Project Name : Stopwatch
  • Create New Project in workspace is selected.
  • For my Build Target I used Android 2.1 this is because some of the features I am using are available in 2.1 and above.
  • Application Name : Stopwatch
  • Package Name : com.shawnbe.stopwatchDemo (note this should be unique, no two applications can have the same package name)
  • Create Activity : StopwatchActivity (this option is also checked)
  • Min SDK Version : 7

 

After creating the new project you should now see a folder with the Project Name.

 

The two main files that we will be working with in this tutorial are the main.xml file and the StopwatchActivity.java, they are located at

 

Stopwatch > src > com.shawnbe.stopwatchDemo > StopwatchActivity.java

and

Stopwatch > res > layout > main.xml

 

The main.xml file is where will be placing the code that handles the layout and look of the application. Go ahead and open the main.xml file.

The main.xml file may open in the Graphical Layout Mode, but its much easier and quicker to get things done by working directly with the .XML file. At the bottom of the new Graphical Layout window you would see two tabs

  • Graphical Layout
  • main.xml
Click on the main.xml tab to view the actual xml data and you should see the following code

<?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">
</LinearLayout>

 

The <LinearLayout> tags show that the root layout element is is a LinearLayout, this is set by default, however for our example we will be using a RelativeLayout, this allows us to have our ad fixed at the bottom of the screen and inside the RelativeLayout we will also put a FrameLayout. The FrameLayout allows us to place a single item across the entire screen, in this case that item we want covering the whole screen is the background.

Before we continue, I should note that all the drawable resources that I provided were designed for HDPI screens for this tutorial, this is not the best practice and  you should design resources such as icons for each type of screen and place them in the corresponding drawable folders. For example if you are designing a menu icon, you should create one at the HDPI resolution, one at the MDPI resolution and one at the LDPI resolution. They should all have the same file names and be placed in the drawable-hdpi , drawable-mdpi and drawable-ldpi folders respectively.

For more information about designing icons at different pixel densities please see these Icon design Guidelines with recommendations about resolution, lighting and more. Although in this tutorial the images are designed for HDPI they will work for each of the three pixel densities. The images can be downloaded from here and a link will also be placed at the end of this tutorial.

Place all of the provided images into the Stopwatch > res > drawable-hdpi folder. We can now reference these resources in our code.

Replace the xml code in the main.xml file 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="fill_parent">
		<FrameLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:id="@+id/parentFrameLayout">
			<ImageView
			android:src="@drawable/background"
			android:scaleType="fitXY"
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/backgroundImageView">
			</ImageView>
		</FrameLayout>
	</RelativeLayout>
 

The code now specifies that the root layout item is a RelativeLayout and within the Layout there is FrameLayout that covers the whole screen with an ImageView (the brushed metal background in our case). You will notice that in the Image View item the android src references the background image you placed in the drawable-hdpi folder. When you reference @drawable, android automatically knows which item it should use and from which drawable folder.

If you were to run the application now on either your handset or the emulator you would see only the background of the application. If you see this then you are on the right track so far.

To run your android project, right click on the project folder within eclipse and Run As > Android Application and will launch your app on the emulator if you have already created an Android Virtual Device, or on your handset if it is plugged in with debugging mode enabled. If you don’t have the correct drivers for your handset then it may not be recognized by adb and will not run on your handset, but it will launch in a new emulator window.

 

 

Now we have the background of the app set, lets add the timer area and the buttons.This is done by adding a vertically oriented Linear Layout this will act as a container that will hold the timer area and the button area.

 

 

The XML file now looks like

<?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="fill_parent">
		<FrameLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:id="@+id/parentFrameLayout">
			<ImageView
			android:src="@drawable/background"
			android:scaleType="fitXY"
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/backgroundImageView">
			</ImageView>
			<LinearLayout
			android:orientation="vertical"
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/linearLayout">
				<LinearLayout
				android:orientation="horizontal"
				android:gravity="center"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:layout_marginTop="20dp"
				android:id="@+id/timerBackground"
				android:background="@drawable/timerbackground">
				</LinearLayout>
				<LinearLayout
				android:orientation="horizontal"
				android:layout_gravity="center_horizontal"
				android:gravity="center"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:layout_marginTop="20dp"
				android:background="@drawable/buttonarea">
				</LinearLayout>
				<LinearLayout
				android:orientation="horizontal"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:layout_gravity="center_horizontal">
					<ImageView
					android:src="@drawable/hline"
					android:layout_height="wrap_content"
					android:layout_gravity="center"
					android:layout_marginTop="20dp"
					android:layout_marginBottom="10dp"
					android:layout_width="wrap_content">
					</ImageView>
				</LinearLayout>
			</LinearLayout>
		</FrameLayout>
	</RelativeLayout>

If you run this project you will now see the blue timer background, the buttons background area and the horizontal separator line.

The next step is to add the text for the timer, the actual buttons in the button area and the ad area at the bottom of the screen, however before we begin, we need to define a couple of Strings that we will be using in the main.xml file. While you can hardcode text using android:text=”your text here” this is not the best practice. It is better to define your text in the strings.xml file as this allows you to update your text without having to change the source code as well as it makes localization of your app a lot easier to manage as seen in this link on localization.The string.xml file is located in the

Stopwatch> res > values > strings.xml file

Open the strings.xml file,  just as with the main.xml file we will be editing the xml code directly rather than using the graphical user interfaces provided. If you have not already done so click on the strings.xml tab at the bottom of the window to switch from the GUI editor to the actual xml code, by default the app_name and hello strings are already created when you open a new Android Project. Update the xml file to reflect the following and save the changes.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, StopwatchActivity!</string>
    <string name="app_name">Stopwatch</string>
    <string name="timer">00:00:00</string>
    <string name="startText">start</string>
    <string name="resetText">reset</string>
    <string name="stopText">stop</string>
    <string name="backgroundText">Stopwatch</string>
    <string name="adsText">Ads Go Here</string>
</resources>

Each of the lines in the xml file represents a new string , the name of the string and the text for that string. For example, the last line “<string name=”adsText”>Ads Go Here</string> means that a string named adsText has been declared and the text for that string is “Ads Go Here”.  Now that we have the new strings defined instead of using android:text=”Ads Go Here” we now use android:text=”@string/adsText”Now lets start on getting the timer text in place. Within the LinearLayout with id=”timerBackground” we will be placing a TextView which will be used to display the stopwatch time. This part of the main.xml file is now updated to be the following

<LinearLayout
android:orientation="horizontal"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:id="@+id/timerBackground"
android:background="@drawable/timerbackground">
        <TextView
        android:textColor="#004254"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:gravity="center"
	android:textSize="60sp"
 	android:text="@string/timer"
 	android:id="@+id/timer">
	</TextView>
</LinearLayout>

 

That takes care of the timer text, now lets look at the buttons. Within the button area we need to add three buttons. Why three? When the Start button is pressed we want that button to disappear and be replaced with a Stop button, by default the stop button will be invisible for now. In a later tutorial we will cover how to use code to make the button appear and reappear. In the buttonarea Linear Layout the xml will now be updated as follows.

<LinearLayout
android:orientation="horizontal"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@drawable/buttonarea">
	<Button
	android:layout_marginLeft="5dp"
	android:layout_marginRight="5dp"
	android:background="@drawable/stopbutton"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_gravity="center"
	android:layout_weight="1"
	android:textColor="#7A1100"
	android:shadowColor="#DF726E"
	android:text="@string/stopText"
	android:id="@+id/stopButton"
	android:visibility="gone">
	</Button>
	<Button
	android:layout_marginLeft="5dp"
	android:background="@drawable/startbutton"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_gravity="center"
	android:textColor="#5F3A00"
	android:shadowColor="#FBEBC5"
	android:layout_weight="1"
	android:text="@string/startText"
	android:id="@+id/startButton">
	</Button>
	<Button
	android:layout_marginRight="5dp"
	android:background="@drawable/resetbutton"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content"
	android:layout_gravity="center"
	android:layout_weight="1"
	android:textColor="#2E2E2E"
	android:shadowColor="#959597"
	android:text="@string/resetText"
	android:id="@+id/resetButton">
	</Button>
</LinearLayout>

Now for the last piece of the layout we will be adding the ad area at the bottom of the screen, to do this we will be using a Relative Layout aligned to the bottom of the Parent Relative Layout. This code will be placed after the Frame Layout, but before the closing tag of the Parent Relative Layout. The last couple of lines of the main.xml file will be (The extra closing RelativeLayout tag at the end is the closing tag from the very first RelativeLayout at the first line in the main.xml file.

<RelativeLayout
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:layout_alignParentBottom="true" >
		<LinearLayout
		android:orientation="vertical"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:background="#000000">
			<TextView
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:gravity="center"
			android:text="@string/adsText">
			</TextView>
		</LinearLayout>
	</RelativeLayout>
</RelativeLayout>

 

At this point the full main.xml file is a follows

 

<?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="fill_parent">
		<FrameLayout
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:id="@+id/parentFrameLayout">
			<ImageView
			android:src="@drawable/background"
			android:scaleType="fitXY"
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/backgroundImageView">
			</ImageView>
			<LinearLayout
			android:orientation="vertical"
			android:layout_width="fill_parent"
			android:layout_height="fill_parent"
			android:id="@+id/linearLayout">
				<LinearLayout
				android:orientation="horizontal"
				android:gravity="center"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:layout_marginTop="20dp"
				android:id="@+id/timerBackground"
				android:background="@drawable/timerbackground">
					<TextView
					android:textColor="#004254"
					android:layout_width="fill_parent"
					android:layout_height="wrap_content"
					android:gravity="center"
					android:textSize="60sp"
 					android:text="@string/timer"
 					android:id="@+id/timer">
					</TextView>
				</LinearLayout>
				<LinearLayout
				android:orientation="horizontal"
				android:layout_gravity="center_horizontal"
				android:gravity="center"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:layout_marginTop="20dp"
				android:background="@drawable/buttonarea">
					<Button
					android:layout_marginLeft="5dp"
					android:layout_marginRight="5dp"
					android:background="@drawable/stopbutton"
					android:layout_width="fill_parent"
					android:layout_height="wrap_content"
					android:layout_gravity="center"
					android:layout_weight="1"
					android:textColor="#7A1100"
					android:shadowColor="#DF726E"
					android:text="@string/stopText"
					android:id="@+id/stopButton"
					android:visibility="gone">
					</Button>
					<Button
					android:layout_marginLeft="5dp"
					android:background="@drawable/startbutton"
					android:layout_width="fill_parent"
					android:layout_height="wrap_content"
					android:layout_gravity="center"
					android:textColor="#5F3A00"
					android:shadowColor="#FBEBC5"
					android:layout_weight="1"
					android:text="@string/startText"
					android:id="@+id/startButton">
					</Button>
					<Button
					android:layout_marginRight="5dp"
					android:background="@drawable/resetbutton"
					android:layout_width="fill_parent"
					android:layout_height="wrap_content"
					android:layout_gravity="center"
					android:layout_weight="1"
					android:textColor="#2E2E2E"
					android:shadowColor="#959597"
					android:text="@string/resetText"
					android:id="@+id/resetButton">
					</Button>
				</LinearLayout>
				<LinearLayout
				android:orientation="horizontal"
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:layout_gravity="center_horizontal">
					<ImageView
					android:src="@drawable/hline"
					android:layout_height="wrap_content"
					android:layout_gravity="center"
					android:layout_marginTop="20dp"
					android:layout_marginBottom="10dp"
					android:layout_width="wrap_content">
					</ImageView>
				</LinearLayout>
				<ScrollView
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:layout_gravity="center_horizontal"
				android:id="@+id/scrollView">
					<TextView
					android:layout_width="fill_parent"
					android:layout_height="fill_parent"
					android:text="@string/backgroundText"
					android:id="@+id/backgroundText">
					</TextView>
				</ScrollView>
			</LinearLayout>
		</FrameLayout>
		<RelativeLayout
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_alignParentBottom="true" >
			<LinearLayout
			android:orientation="vertical"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:background="#000000">
				<TextView
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:gravity="center"
				android:text="@string/adsText">
				</TextView>
			</LinearLayout>
		</RelativeLayout>
	</RelativeLayout>

 

If you run the project you should see the layout coming together, its not quite there as yet, but we will continue on in the next tutorial, which will cover the final touches to get the layout looking a bit more polished. We will cover using custom fonts , button states and styles for the text items. See you soon.

Below are the download links for the image resources and completed xml file.


Resources

Image Resources

Completed XML File

 

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>