Saturday, February 6, 2010

Tutorial: Listview

Android "To Do" Application Tutorial

This is Part 1 in a series of tutorials. Each will build on the previous covering concepts which should be transferable to many applications. In order to cover many typical coding requirements, we are going to create a simple "To Do" application. Each tutorial part will conclude with a functioning application, albeit incomplete. In these series of tutorials we will cover adding, editing, and deleting items in a ListView. Here is what this series of tutorials will cover:
  • Start a new Android application.
  • Add, edit, and delete items in a ListView.
  • Edit "To Do" form.
  • We will start with a simple "one line" ListView. Then we will upgrade it so we can customize and dress up each row.
  • We will add some graphics to the ListView.
  • To improve performance and encapsulation we will move To Do items into a separate class that can  cache the TextView and ImageView widgets.
  • Create a landscape layout.
  • Create a database and table to store our tasks.
 Part 1: Create a new project



1. Create new project

     
2. Select "Android Application". Select "Next"

3. Set new project properties the click "Finish"
  • Project Name: To Do Tutorial
  • Build Target: Select Android 2.1 (you may select any build target, but this tutorial is 2.1)
  • Application Name: To Do Tutorial
  • Package Name: org.androidcodemonkey.todo
  • Create Activity: DetailForm
  • Min SDK: 7 (leave the default)

4. Open layout "main.xml"

5. Right click on "Hello World, DetailForm!" and select "Remove"
6. Now we are going to modify our layout. You can drag controls onto the layout in "Layout" mode, but I prefer to edit the XML directly. It provides me greater control. I am going to add the following controls in the XML mode (add the code from lines 2-26):
  • TableLayout
    • TableRow
      • TextView
      • EditText
    • TableRow
      • TextView
      • RadioGroup
        • RadioButton
        • RadioButton
        • RadioButton
    • TableRow
      • TextView
      • Button

 
  
   
   
  
  
   
   
     
     
     
   
  
  
   
   
 



  
   
  



7. Change to LayoutView and it should look like this. Feel free to change settings on the display to see how it affects the controls.
 
8. Now we need an "entity" class. To keep our class files organized, let's create package.
  • In the Package Explorer > Right click on "src" > "New" > "Package"

  • Name: "org.androidcodemonkey.entities" Then click "Finish"
9. Let's add the a class for our "Task"
  • In the Package Explorer > Right click on "org.androidcodemonkey.entities" > "New" > "class"
  • Name: TaskBE. Click "Finish"
10. Create the following properties and methods.
  • Create string "item"
  • Create string "priority"
  • Create getItem() 
  • Create setItem()
  • Create getPriority()
  • Create setPriority()
  • Implement "toString()". 
Your TaskBE class should look like this:

package org.androidcodemonkey.entities;

public class TaskBE {
 private String item="";
 private String priority="";
 
 public String getItem() {
  return(item);
 }
 
 public void setItem(String value) {
  this.item = value;
 }
 public String getPriority() {
  return(priority);
 }
 public void setType(String value) {
  this.priority = value;
 }
 public String toString() {
  return(getItem());
 }
}
11. Open DetailForm.java. We are going to add an "onSave" method that will be called when the save button is pressed. When the save button is pressed we are going to retrieve the information from the View.
  • Import reference to entities (line #3)
  • Create a new TaskBE object. (line #20)
  • Create an EditText to retrieve the item entered into the view (line #21)
  • Set the item property of the Task (line #22)
  • Create a RadioGroup to retrieve the priority (line #23)
  • Set the priority property of the task (lines #24-#34)
  • (In the next post we will implement adding the task to an adapter) (line #35)
  • Clear the controls on View (lines #37-#38)
package org.androidcodemonkey.todo;

import org.androidcodemonkey.entities.*;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;

public class DetailForm extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
private View.OnClickListener onSave=new View.OnClickListener() {
 public void onClick(View v) {
  TaskBE newTask =new TaskBE();
  EditText taskItem=(EditText)findViewById(R.id.txtTask);
  newTask.setItem(taskItem.getText().toString());
  RadioGroup priorityGroup=(RadioGroup)findViewById(R.id.priority);
  switch (priorityGroup.getCheckedRadioButtonId()) {
   case R.id.highPriority:
    newTask.setType("high_priority");
    break;
   case R.id.medPriority:
    newTask.setType("med_priority");
    break;
   case R.id.lowPriority:
    newTask.setType("low_priority");
    break;
  }
  //To do - Add task to adapter. To be implemented in next post
  //Clear form
  taskItem.setText("");
  priorityGroup.clearCheck();
  }
 };    

}


12. Now when the form is created we need instantiate a button and set it to the save button (line #18) and register a callback for when the button is pressed (line #19).
package org.androidcodemonkey.todo;

import org.androidcodemonkey.entities.*;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;

public class DetailForm extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btnSave = (Button)findViewById(R.id.btnSave);
        btnSave.setOnClickListener(onSave);
        
    }
private View.OnClickListener onSave=new View.OnClickListener() {
 public void onClick(View v) {
  TaskBE newTask =new TaskBE();
  EditText taskItem=(EditText)findViewById(R.id.txtTask);
  newTask.setItem(taskItem.getText().toString());
  RadioGroup priorityGroup=(RadioGroup)findViewById(R.id.priority);
  switch (priorityGroup.getCheckedRadioButtonId()) {
   case R.id.highPriority:
    newTask.setType("high_priority");
    break;
   case R.id.medPriority:
    newTask.setType("med_priority");
    break;
   case R.id.lowPriority:
    newTask.setType("low_priority");
    break;
  }
  //To do - Add task to adapter. To be implemented in next post
  //Clear form
  taskItem.setText("");
  priorityGroup.clearCheck();
  }
 };    

}
13. You can now run the program. When you click "Save" your controls should be cleared. Your screen should look like this


Following is the complete code

Download zip file of complete Eclipse project





DetailFrom.java
package org.androidcodemonkey.todo;

import org.androidcodemonkey.entities.*;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;

public class DetailForm extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btnSave = (Button)findViewById(R.id.btnSave);
        btnSave.setOnClickListener(onSave);
        
    }
private View.OnClickListener onSave=new View.OnClickListener() {
 public void onClick(View v) {
  TaskBE newTask =new TaskBE();
  EditText taskItem=(EditText)findViewById(R.id.txtTask);
  newTask.setItem(taskItem.getText().toString());
  RadioGroup priorityGroup=(RadioGroup)findViewById(R.id.priority);
  switch (priorityGroup.getCheckedRadioButtonId()) {
   case R.id.highPriority:
    newTask.setType("high_priority");
    break;
   case R.id.medPriority:
    newTask.setType("med_priority");
    break;
   case R.id.lowPriority:
    newTask.setType("low_priority");
    break;
  }
  //To do - Add task to adapter. To be implemented in next post
  //Clear form
  taskItem.setText("");
  priorityGroup.clearCheck();
  }
 };    

}
TaskBE.java

package org.androidcodemonkey.entities;

public class TaskBE {
 private String item="";
 private String priority="";
 
 public String getItem() {
  return(item);
 }
 
 public void setItem(String value) {
  this.item = value;
 }
 public String getPriority() {
  return(priority);
 }
 public void setType(String value) {
  this.priority = value;
 }
 public String toString() {
  return(getItem());
 }
}