Continuing my tutorials on some UI related stuff… In Part 16 & 17, I spoke about Simple ListView and Custom ListView. In Part 18, though it seems like a tutorial on Threads and Handlers, I have touched upon ProgressDialog, another view.
Here I would like to talk on the DatePicker and TimePicker that are bundled with the SDK. Both are very similar. So, I will talk only about DatePicker, but the sample code will have both.
Typically, we would want an end user to be able to set a date though a DatePickerDialog that pops-up on some user action. So, I have a button “Set Date” on the click of which a DatePickerDialog pops-up. Once the user selects a date and “sets” it, it is displayed back in a TextView field.
So, the code associated with the button is:
pickDate.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
showDialog(DATE_DIALOG_ID);
}
});
showDialog(…) is a method available on an Activity Itself. It just takes an integer to help decide which dialog should actually be shown. This is decided in the onCreateDialog(…) method that gets automatically invoked when showDialog(…) is called.
Here is the code for the same:
protected Dialog onCreateDialog(int id){
switch(id) {
case DATE_DIALOG_ID:
return new DatePickerDialog(this, dateListener, year, month, day);
case ….
}
return null;
}
In this method, when the int passed is DATE_DIALOG_ID, a new DatePickerDialog is passed along with the values for year, month and day. Where did I set values for these? In the onCreate(…) method itself, I have done this:
final Calendar cal = Calendar.getInstance();
year = cal.get(Calendar.YEAR);
month = cal.get(Calendar.MONTH);
day = cal.get(Calendar.DAY_OF_MONTH);
Also note that a handle to a listener is expected to be given to the DatePickerDialog. I will come to this listener a little later.
I have also updated the Date - TextView with these values in the updateDate() method which is invoked in the onCreate(…) method itself.
private void updateTime() {
timeDisplay.setText(new StringBuilder().append(hours).append(':')
.append(min));
}
So far, what I have done is shown how to create a Dialog and set the date.
Once the dialog shows up, when a user sets the date and clicks ‘set’, the listener that is invoked in on the DatePickerDialog. The method is onDateSetListener whose handle is passed during the creation of the DatePickerDialog itself.
private DatePickerDialog.OnDateSetListener dateListener =
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int yr, int monthOfYear, int dayOfMonth) {
year = yr;
month = monthOfYear;
day = dayOfMonth;
updateDate();
}
};
In this method, on the click on the dialog, we are setting the day, month, year values to the new values that the user selected and also calling the updateDate() method to refresh the TextView with what the user selected.
It is this simple.
Same thing can be done with the TimePicker as well. The only difference is that you can pass a Boolean variable to say whether you want the time in 24 hour or 12 hour pattern.
Here is the complete code for the same.
Sunday, May 9, 2010
Wednesday, May 5, 2010
Http Connection Using Threads & Handlers in Android (Part 19)
This is about how to invoke an Http Url from an android activity. If you have already written such a program in core java, you will not find anything new in the HTTP connectivity part. However, this tutorial also shows how to communicate between thread using the Message object.
In this tutorial, I plan to download 1 image and 1 text from the internet on the click of respective buttons on the android phone.
NOTE: I have also incidentally used Absolute Layout so that the buttons, the text and the image are all seen on the same screen even after being fetched.
Since fetching data from the internet can be a time-consuming task and a very unpredictable one at that, so, it would best be done in a separate thread rather than the UI/main thread. The basics of this have been discussed in the previous tutorial on Handlers and Threads.
To go to the application code directly, on the click of a button “Get Image”, I want to get an image whose URL is hard-coded in the program. For that first, I must open an HTTP connection to the server and then request for the image.
Hence is the code for opening and making an HTTP Connection:
So, this is a utility method that I will use for fetching image as well as text.
Now, coming to fetching the image. I want to fetch it when the end user clicks on a button “Get Image”. So the code associated with the button click is here:
});
So the fetching of the image is in the downloadImage() method, which is given the URL of the android logo. Here is the method:
progressDialog = ProgressDialog.show(this, "", "Fetching Image...");
Then, I start a new thread. I make the URL string accessible within the new thread by making it a final variable. Since message is an object that I can use for communication between threads, I create a Message object in the thread. Then, I set the message number to 1, so that I can use it later.
Once I close the input stream as in:
As soon as the child thread notifies, the method called back in the main thread is the handleMessage(msg) method. It is in this method that I retrieve the bitmap and set it to the ImageView in the UI. Here it goes:
Within this method, first I check the msg.what variable to see what the type of message I am expecting is. If it is 1, which I had set in downloadImage(..) method, then, I do the required things to get a handle to the ImageView object and then give the bitmap to it.
How do I fetch the data from the msg object? Through getData(). Then I use the key “bitmap” to retrieve the bitmap and cast it to Bitmap before setting it to the ImageView. Finally, I dismiss the progress dialog.
I hope this is clear. This example not only shows HTTP Connection from Android but also the Thread-to-thread communication through handler, message exchange.
In a very similar fashion, I also fetch the text. On click of the Get Text button, here is the code that gets invoked:
The downloadText() code is here:
private void downloadText(String urlStr) {
progressDialog = ProgressDialog.show(this, "", "Fetching Text...");
final String url = urlStr;
And the way the text is handled in the main thread handleMessage(..) method is here:
In this tutorial, I plan to download 1 image and 1 text from the internet on the click of respective buttons on the android phone.
NOTE: I have also incidentally used Absolute Layout so that the buttons, the text and the image are all seen on the same screen even after being fetched.
Since fetching data from the internet can be a time-consuming task and a very unpredictable one at that, so, it would best be done in a separate thread rather than the UI/main thread. The basics of this have been discussed in the previous tutorial on Handlers and Threads.
To go to the application code directly, on the click of a button “Get Image”, I want to get an image whose URL is hard-coded in the program. For that first, I must open an HTTP connection to the server and then request for the image.
Hence is the code for opening and making an HTTP Connection:
private InputStream openHttpConnection(String urlStr) {I will not be explaining this code much as most of this is based on the java.net package. This code would be exactly same even if we were to write this in regular java code, not meant for android usage. In brief, I have opened a URLConnection, checked if it is an instance of HttpURLConnection, set the parameters required and made the ‘connection’ finally by calling the connect() method. Then, I check if the response code is OK and I get a handle to the input stream.
InputStream in = null;
int resCode = -1;try {return in;URL url = new URL(urlStr);} catch (MalformedURLException e) {
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpURLConnection)) {}throw new IOException ("URL is not an Http URL");
HttpURLConnection httpConn = (HttpURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
resCode = httpConn.getResponseCode();
if (resCode == HttpURLConnection.HTTP_OK) {}in = httpConn.getInputStream();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
So, this is a utility method that I will use for fetching image as well as text.
Now, coming to fetching the image. I want to fetch it when the end user clicks on a button “Get Image”. So the code associated with the button click is here:
getImageButton = (Button)findViewById(R.id.Button01);
getImageButton.setOnClickListener( new OnClickListener() {}Override
public void onClick(View v) {
downloadImage(http://www.android.com/media/wallpaper/gif/android_logo.gif);
});
So the fetching of the image is in the downloadImage() method, which is given the URL of the android logo. Here is the method:
private void downloadImage(String urlStr) {This method looks a bit complicated. First, let us look at the basics. If I were not fetching this in a separate thread, I would have just the 3 lines of code that is in Bold and highlighted. Open a connection, fetch the bitmap and close the connection. However, since this is a typical task that is unpredictable in its response time, it is best done in a separate thread of its own. So, before I start a new thread, I let the UI thread to show a ProgressDialog as shown in
progressDialog = ProgressDialog.show(this, "", "Fetching Image...");
final String url = urlStr;new Thread() {
public void run() {
InputStream in = null;
Message msg = Message.obtain();
msg.what = 1;
try {in = openHttpConnection(url);messageHandler.sendMessage(msg);
bitmap = BitmapFactory.decodeStream(in);
Bundle b = new Bundle();
b.putParcelable("bitmap", bitmap);
msg.setData(b);
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}.start();
progressDialog = ProgressDialog.show(this, "", "Fetching Image...");
Then, I start a new thread. I make the URL string accessible within the new thread by making it a final variable. Since message is an object that I can use for communication between threads, I create a Message object in the thread. Then, I set the message number to 1, so that I can use it later.
Then, I bundle my bitmap already fetched into a Bundle object that can be sent back in the Message object.Message msg = Message.obtain();
msg.what = 1;
Bundle b = new Bundle();
b.putParcelable("bitmap", bitmap);
msg.setData(b);
Once I close the input stream as in:
in.close();the thread has completed the job. So, I notify the main / UI thread through this method and also pass on the Message object:
messageHandler.sendMessage(msg);This completes the fetching of the image in a separate thread. Now, how do I retrieve the image from the Message object in the main thread?
As soon as the child thread notifies, the method called back in the main thread is the handleMessage(msg) method. It is in this method that I retrieve the bitmap and set it to the ImageView in the UI. Here it goes:
private Handler messageHandler = new Handler() {};public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:ImageView img = (ImageView) findViewById(R.id.imageview01);case 2:
img.setImageBitmap((Bitmap)(msg.getData().getParcelable("bitmap")));
break;
……….
}
progressDialog.dismiss();
}
Within this method, first I check the msg.what variable to see what the type of message I am expecting is. If it is 1, which I had set in downloadImage(..) method, then, I do the required things to get a handle to the ImageView object and then give the bitmap to it.
How do I fetch the data from the msg object? Through getData(). Then I use the key “bitmap” to retrieve the bitmap and cast it to Bitmap before setting it to the ImageView. Finally, I dismiss the progress dialog.
I hope this is clear. This example not only shows HTTP Connection from Android but also the Thread-to-thread communication through handler, message exchange.
In a very similar fashion, I also fetch the text. On click of the Get Text button, here is the code that gets invoked:
getTextButton.setOnClickListener(new OnClickListener() {});
@Overridepublic void onClick(View v) {
downloadText(http://saigeethamn.blogspot.com/feeds/posts/default);
}
The downloadText() code is here:
private void downloadText(String urlStr) {
progressDialog = ProgressDialog.show(this, "", "Fetching Text...");
final String url = urlStr;
new Thread () {
public void run() {}
int BUFFER_SIZE = 2000;
InputStream in = null;
Message msg = Message.obtain();
msg.what=2;
try {in = openHttpConnection(url);} catch (IOException e) {
InputStreamReader isr = new InputStreamReader(in);
int charRead;
text = "";
char[] inputBuffer = new char[BUFFER_SIZE];
while ((charRead = isr.read(inputBuffer))>0)
{
//---convert the chars to a String---
String readString =
String.copyValueOf(inputBuffer, 0, charRead);
text += readString;
inputBuffer = new char[BUFFER_SIZE];
}
Bundle b = new Bundle();
b.putString("text", text);
msg.setData(b);
in.close();
e.printStackTrace();
}
messageHandler.sendMessage(msg);
}
}.start();
And the way the text is handled in the main thread handleMessage(..) method is here:
case 2:The complete code can be downloaded here
TextView text = (TextView) findViewById(R.id.textview01);
text.setText(msg.getData().getString("text"));
break;
Thanks for your understanding.
NOTE: the blog editor is posing major problems in editing - it is jumbling up the whole post esp. when I use the " feature. So, please bear with me if somethings look garbled. I have tried my best to work around the editor problem. This has been noticed only in the last 3 posts of mine. Hope it gets fixed soon.
Monday, April 26, 2010
Threads and Handlers | Android Developer Tutorial (Part 18)
Any mobile software development needs to be done with an awareness of the end user experience. This is true in any other domain as well. But special mention here on mobile development as end users are used to responsive apps on the mobile and any small delay is perceived as un-responsiveness or worse – that the application has hung.
One of the basic principles to provide a very responsive application is to handle any time consuming code in a separate thread – not the main thread or the UI thread as it is also known. So, it is very essential to understand about how to spawn new threads (worker or background threads) and how to come back to the parent thread.
How do the 2 threads (parent/UI and the worker threads) communicate? Here comes the Handler. By definition – “A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.”
So, let us take the handler from the main thread and see how we can use it to communicate with a child thread.
When a handler is created, it is associated by default with the current thread. So, we have this piece of code in the main activity class:
Now, I spawn a new thread through a method that is called when I click a button. So, let us see the button piece of code first:
Now, on click of the button, the fetchData() method is invoked. Assuming that this is a very time consuming task, I will spawn a thread and do the task and return from that thread as shown in the code below:
}.start();
}
Since it is time consuming, I am starting a ProgressDialog just to inform the end user that some activity is happening. Then, I start the thread, make it sleep for 800 milliseconds and send back an empty message through the message handler. The messageHandler.sendEmptyMessage(0) is the callback on the parent thread’s messageHandler to inform that the child thread has finished its work. In this example I am sending an empty message. But this can be the means of communication and exchange of data from the child thread to the parent Thread.
Now the control returns to handleMessage() call back method. That method shown in the beginning just dismisses the progressDialog.
In real life cases, within this thread we can do things like calling web-services, calling web-sites to fetch specific data or doing network IO operations and returning actual data that needs to be displayed on the front-end.
I will take up an example of an HTTP call invoked through such a thread in the next tutorial.
Also note that the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread only. So the child thread should return all data and the painting of the UI should be left to the main thread or any UI specific thread.
There is a better way of handling this through the use of AsyncTask, a utility class available from SDK 1.5 onwards. It was available as UserTask earlier.
Here is the complete downloadable code for this tutorial.
One of the basic principles to provide a very responsive application is to handle any time consuming code in a separate thread – not the main thread or the UI thread as it is also known. So, it is very essential to understand about how to spawn new threads (worker or background threads) and how to come back to the parent thread.
How do the 2 threads (parent/UI and the worker threads) communicate? Here comes the Handler. By definition – “A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.”
So, let us take the handler from the main thread and see how we can use it to communicate with a child thread.
When a handler is created, it is associated by default with the current thread. So, we have this piece of code in the main activity class:
Now, I spawn a new thread through a method that is called when I click a button. So, let us see the button piece of code first:
private Handler messageHandler = new Handler() {
};
public void handleMessage(Message msg) {
super.handleMessage(msg);
progressDialog.dismiss();
}
start = (Button) findViewById(R.id.Button01);
start.setOnClickListener(new OnClickListener() {});
@Override
public void onClick(View arg0) {
fetchData();
}
Now, on click of the button, the fetchData() method is invoked. Assuming that this is a very time consuming task, I will spawn a thread and do the task and return from that thread as shown in the code below:
protected void fetchData() {
progressDialog = ProgressDialog.show(this, "", "Doing...");
new Thread() {
public void run() {
try {
Thread.sleep(800);} catch (InterruptedException e) {
}
messageHandler.sendEmptyMessage(0);
}
}.start();
}
Since it is time consuming, I am starting a ProgressDialog just to inform the end user that some activity is happening. Then, I start the thread, make it sleep for 800 milliseconds and send back an empty message through the message handler. The messageHandler.sendEmptyMessage(0) is the callback on the parent thread’s messageHandler to inform that the child thread has finished its work. In this example I am sending an empty message. But this can be the means of communication and exchange of data from the child thread to the parent Thread.
Now the control returns to handleMessage() call back method. That method shown in the beginning just dismisses the progressDialog.
In real life cases, within this thread we can do things like calling web-services, calling web-sites to fetch specific data or doing network IO operations and returning actual data that needs to be displayed on the front-end.
I will take up an example of an HTTP call invoked through such a thread in the next tutorial.
Also note that the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread only. So the child thread should return all data and the painting of the UI should be left to the main thread or any UI specific thread.
There is a better way of handling this through the use of AsyncTask, a utility class available from SDK 1.5 onwards. It was available as UserTask earlier.
Here is the complete downloadable code for this tutorial.
Monday, April 19, 2010
Custom ListView | Android Developer Tutorial (Part 17)
Now, we shall look at creating a custom list view – a custom layout, a custom row layout and how we bind the custom data holder to these layouts. (please see the earlier article on simple list view for the fundamentals of list view).
So, here again, we start with extending ListActivity.
Now let us create the custom list view in an xml file – custom_list_view.xml. This will be set using the setContentView() in onCreate() method:
I have also declared a TextView which should be whon when the list if empty by declaring with android:id="@id/android:empty"
Now we will declare how each row in this ListView should be displayed by creating a new xml file – custom_row_view.xml
I plan to have 3 items one below the other in each row. So, here is the declaration for the same:
An adapter expects the context, the layout and the handle to the data that needs to be displayed. So, let us create a list of data in an ArrayList of HashMaps. This way, the HashMap can store any amount of data.
This list is populated in a method as shown below with the 3 keys as ‘pen’, ‘price’ and ‘color’:
Then, using the SimpleAdapter, we have set the context, the list containing the data for display, the custom_row_view, the keys by which the data has to be fetched from the list, the TextViews into which the corresponding data has to be displayed.
Now execute and you will have a custom list view. Here is what you will get to see:
NOTE: if you do not populate the list with any data, you will see another view – the empty listview that we have defined in the custom_list_view.xml
You can download the complete source code for this example here.
Added later:
Based on a question below, I would like to add that an item can be clicked even in this custom list and the even captured by overriding the onListItemClick() method on the ListActivity class.
Here is the piece of code you can add to my sample, if you haev downlaoded and ti will toast a message on what has been selected:
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Object o = this.getListAdapter().getItem(position);
String pen = o.toString();
Toast.makeText(this, "You have chosen the pen: " + " " + pen, Toast.LENGTH_LONG).show();
}
Enjoy....
So, here again, we start with extending ListActivity.
public class MyCustomListView extends ListActivity {
Now let us create the custom list view in an xml file – custom_list_view.xml. This will be set using the setContentView() in onCreate() method:
<ListView android:id="@id/android:list"Note that it must contain a ListView object with android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000fff"
android:layout_weight="2"
android:drawSelectorOnTop="false">
</ListView>
<TextView android:id="@id/android:empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFff00"
android:text="No data"
/>
I have also declared a TextView which should be whon when the list if empty by declaring with android:id="@id/android:empty"
Now we will declare how each row in this ListView should be displayed by creating a new xml file – custom_row_view.xml
I plan to have 3 items one below the other in each row. So, here is the declaration for the same:
<TextView android:id="@+id/text1"So, now, how do I tie all of this together? The MyCustomListView class, the listview layout and the row layout. Just like in the earlier example, we need a ListAdpater object. Here I plan to use a SimpleAdpater provided by the SDK.
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#FFFF00"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="@+id/text2"
android:textSize="12sp"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="fill_parent"/>
<TextView android:id="@+id/text3"
android:typeface="sans"
android:textSize="14sp"
android:textStyle="italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
An adapter expects the context, the layout and the handle to the data that needs to be displayed. So, let us create a list of data in an ArrayList of HashMaps. This way, the HashMap can store any amount of data.
static final ArrayList<HashMap<String,String>> list =This is just a declaration of the list object. We need to populate it with data. Our custom row layout expects each row to have 3 prices of data…
new ArrayList<HashMap<String,String>>();
This list is populated in a method as shown below with the 3 keys as ‘pen’, ‘price’ and ‘color’:
private void populateList() {
HashMap<String,String> temp = new HashMap<String,String>();So, now how do we tie up the data with the row layout and the listview layout. It is in this simple piece of code in the onCreate() method of MyCustomListView class:
temp.put("pen","MONT Blanc");
temp.put("price", "200.00$");
temp.put("color", "Silver, Grey, Black");
list.add(temp);
HashMap<String,String> temp1 = new HashMap<String,String>();
temp1.put("pen","Gucci");
temp1.put("price", "300.00$");
temp1.put("color", "Gold, Red");
list.add(temp1);
HashMap<String,String> temp2 = new HashMap<String,String>();
temp2.put("pen","Parker");
temp2.put("price", "400.00$");
temp2.put("color", "Gold, Blue");
list.add(temp2);
HashMap<String,String> temp3 = new HashMap<String,String>();
temp3.put("pen","Sailor");
temp3.put("price", "500.00$");
temp3.put("color", "Silver");
list.add(temp3);
HashMap<String,String> temp4 = new HashMap<String,String>();
temp4.put("pen","Porsche Design");
temp4.put("price", "600.00$");
temp4.put("color", "Silver, Grey, Red");
list.add(temp4);
}
setContentView(R.layout.custom_list_view);
SimpleAdapter adapter = new SimpleAdapter(
this,
list,
R.layout.custom_row_view,
new String[] {"pen","price","color"},
new int[] {R.id.text1,R.id.text2, R.id.text3}
);
populateList();Here we have set the default view to custom_list_view.
setListAdapter(adapter);
Then, using the SimpleAdapter, we have set the context, the list containing the data for display, the custom_row_view, the keys by which the data has to be fetched from the list, the TextViews into which the corresponding data has to be displayed.
Now execute and you will have a custom list view. Here is what you will get to see:
NOTE: if you do not populate the list with any data, you will see another view – the empty listview that we have defined in the custom_list_view.xml
You can download the complete source code for this example here.
Added later:
Based on a question below, I would like to add that an item can be clicked even in this custom list and the even captured by overriding the onListItemClick() method on the ListActivity class.
Here is the piece of code you can add to my sample, if you haev downlaoded and ti will toast a message on what has been selected:
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Object o = this.getListAdapter().getItem(position);
String pen = o.toString();
Toast.makeText(this, "You have chosen the pen: " + " " + pen, Toast.LENGTH_LONG).show();
}
Enjoy....
Wednesday, April 7, 2010
Simple ListView | Android Developer Tutorial (Part 16)
From exploring the various concepts related to fundamentals and to locations and maps, I would like to look at a few UI elements.
One of the simple views is a List View. In this post, I will explore a very simple list view using all the defaults provided by Android SDK and introduce you to a customized list view in the next blog article.
A List View, by name means being able to display a list of items in an order one below the other. For creating such a view, the first thing we have to do is extend the ‘ListActivity’ (android.app.ListActivity) instead of the normal Activity class.
So, here is how the class declaration should look:
In android, we all know that views are defined declaratively in XML files. It is the same here too. So, if we were to create our own custom ListView, we would have a declaration of this type:
However, if no ListView is declared, the ListActivity picks up a default ListView which fills the screen. So, in our example we will not declare any list view.
There is one more thing we need to define and that is how each row in the list should show up. This again, there are some defaults available which have names such as simple_list_item_1, simple_list_item_2, and two_line_list_item. So, in our example, I do not declare the layout for the rows but I will be using one of the defaults provided. So, in effect, I have not declared any layout – I am using the default screen layout and row layout.
Now, that we have the layouts out of our way, what else do we need for a List View. Of course, the list of data that needs to be displayed. Just to keep it simple, I will use an array of data for the same. So, here it is:
Now, how do I bind this data to the default views described earlier? This is aided by a ListAdapter interface hosted by the ListActivity class that we have extended.
We need to use the setListAdapter(..) method of the ListActivity class to bid the two (data and view). Android provides many implementations of the ListAdapter. We will use the simple ArrayAdapter.
What does the ArrayAdapter expect?
It expects the context object, the row layout and the data in an array.
So here it is:
I have added a small piece of code to show we can handle events on selecting an item in the list, by overriding the protected method shown below:
This toasts a message with the item selected.
The complete code is downloadable here.
One of the simple views is a List View. In this post, I will explore a very simple list view using all the defaults provided by Android SDK and introduce you to a customized list view in the next blog article.
A List View, by name means being able to display a list of items in an order one below the other. For creating such a view, the first thing we have to do is extend the ‘ListActivity’ (android.app.ListActivity) instead of the normal Activity class.
So, here is how the class declaration should look:
public class MyListView extends ListActivity {The ListActivity class provides a way of binding a source of data (an array or a cursor) to a ListView object through a ListAdapter.
In android, we all know that views are defined declaratively in XML files. It is the same here too. So, if we were to create our own custom ListView, we would have a declaration of this type:
<ListView android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000fff"
android:layout_weight="2"
android:drawSelectorOnTop="false">
</ListView>
However, if no ListView is declared, the ListActivity picks up a default ListView which fills the screen. So, in our example we will not declare any list view.
There is one more thing we need to define and that is how each row in the list should show up. This again, there are some defaults available which have names such as simple_list_item_1, simple_list_item_2, and two_line_list_item. So, in our example, I do not declare the layout for the rows but I will be using one of the defaults provided. So, in effect, I have not declared any layout – I am using the default screen layout and row layout.
Now, that we have the layouts out of our way, what else do we need for a List View. Of course, the list of data that needs to be displayed. Just to keep it simple, I will use an array of data for the same. So, here it is:
static final String[] PENS = new String[]{
"MONT Blanc",
"Gucci",
"Parker",
"Sailor",
"Porsche Design",
"Rotring",
"Sheaffer",
"Waterman"
};
Now, how do I bind this data to the default views described earlier? This is aided by a ListAdapter interface hosted by the ListActivity class that we have extended.
We need to use the setListAdapter(..) method of the ListActivity class to bid the two (data and view). Android provides many implementations of the ListAdapter. We will use the simple ArrayAdapter.
What does the ArrayAdapter expect?
It expects the context object, the row layout and the data in an array.
So here it is:
setListAdapter(new ArrayAdapter<String>(this,With this we are done in creating the ListView.
android.R.layout.simple_list_item_1, PENS));
I have added a small piece of code to show we can handle events on selecting an item in the list, by overriding the protected method shown below:
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Object o = this.getListAdapter().getItem(position);
String pen = o.toString();
Toast.makeText(this, "You have chosen the pen: " + " " + pen, Toast.LENGTH_LONG).show();
}
This toasts a message with the item selected.
The complete code is downloadable here.
Thursday, March 25, 2010
Basic steps for upgrading source code from SDK 1.5 to 2.1 using Eclipse IDE
This is a step by step guide to upgrade one’s source code that was developed for an earlier version of android SDK, as is to work on a new version of SDK installed on your development environment
Pre-requisites:
1. You are using Eclipse IDE - Ganymede
2. You have installed SDK 2.1 on your machine
3. You have upgraded ADT to 0.96 on Eclipse IDE
4. You have pointed the Eclipse IDE to the new SDK 2.1
5. You have changed the default JDK compiler version on Eclipse to 1.6
6. You have created an Android Virtual Device (AVD) that uses the SDK 2.1 / Google API
NOTE: Upgrading SDK and Eclipse installations itself is provided in detail at http://developer.android.com/sdk/index.html & http://developer.android.com/sdk/installing.html
For each project that you have in your eclipse workspace that was written for the earlier version of SDK, you need to do the following for basic upgrade (this does not include the upgrade of APIs that have be deprecated):
Step-by-step guide
1. Right click the project and go to Project Properties -> Android
2. You wil see tha right pane showing the ‘Project Build Target’
3. In this pane you will see either or both: ‘Android 2.1’ & ‘Google APIs’ depending on what you chose to install when upgrading your ADT to 0.96
4. Select Google ‘Android 2.1’ or ‘Google API” whichever is required by your earlier project (note you might have used only Android 1.5 for most projects. You would need Google API only for those projects that use google maps)
5. Then, go to the ‘Project’ menu and click on ‘clean’. Note, this is an optional step. You may have to do this if you get the error ‘Conversion to Dalvik format failed with error 1’.
6. Then, build the project by going to ‘Project’ -> ‘build’
7. You are done. You can now run the earlier Android application using the new SDK 2.1
Pre-requisites:
1. You are using Eclipse IDE - Ganymede
2. You have installed SDK 2.1 on your machine
3. You have upgraded ADT to 0.96 on Eclipse IDE
4. You have pointed the Eclipse IDE to the new SDK 2.1
5. You have changed the default JDK compiler version on Eclipse to 1.6
6. You have created an Android Virtual Device (AVD) that uses the SDK 2.1 / Google API
NOTE: Upgrading SDK and Eclipse installations itself is provided in detail at http://developer.android.com/sdk/index.html & http://developer.android.com/sdk/installing.html
For each project that you have in your eclipse workspace that was written for the earlier version of SDK, you need to do the following for basic upgrade (this does not include the upgrade of APIs that have be deprecated):
Step-by-step guide
1. Right click the project and go to Project Properties -> Android
2. You wil see tha right pane showing the ‘Project Build Target’
3. In this pane you will see either or both: ‘Android 2.1’ & ‘Google APIs’ depending on what you chose to install when upgrading your ADT to 0.96
4. Select Google ‘Android 2.1’ or ‘Google API” whichever is required by your earlier project (note you might have used only Android 1.5 for most projects. You would need Google API only for those projects that use google maps)
5. Then, go to the ‘Project’ menu and click on ‘clean’. Note, this is an optional step. You may have to do this if you get the error ‘Conversion to Dalvik format failed with error 1’.
6. Then, build the project by going to ‘Project’ -> ‘build’
7. You are done. You can now run the earlier Android application using the new SDK 2.1
Tuesday, March 16, 2010
Will be back
Thanks for the overwhleming response of good words on my blog, for the tutorials I have put up. I am also getting a lot of requests for new tutorials. I have not been able to respond to all requests for sometime now. It will be another month (some time in mid april) when I will again actively start blogging my tutorials on various topics (a little more advanced), based on all your requests. Meanwhile, hope you are able to benefit from what I have already put it.
Subscribe to:
Posts (Atom)