Search This Blog

Sunday, December 13, 2009

WhitePage Application_Part 2

In my last post we saw how the main page of our application works, in this post we will be discussing some other features of our application. if you remember, the result of our search is shown in a page like this:





I've used ListView for this page and here is our layout file for this page :



<?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"
android:baselineAligned="true">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/resultLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="true"
android:background="@color/black"
android:layout_margin="2dip"
android:scrollbars="horizontal">


<ListView android:text=" text "
android:id="@+id/listView"
android:minWidth="70dip"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="5dip"
android:divider="@color/white"
android:dividerHeight="10dip"/>






</LinearLayout>

</LinearLayout>



it's pretty simple,isn't it? what we need to know is how to tell to a ListView to show whatever we want to show and and how to format it. in our case after each search we will have an array of Result class, Result objects are simple POJOs which have a name, address and a phone number,we also want to show our result is three different lines(you might need to show an image in each row or have a more complicated structure for each row).
ListView uses something called ListAdapter to get all data needed to be shown and know how to show it, there are some predefined subclasses of ListAdapter such as ArrayAdapter, CursorAdapter and SimpleAdapter which provide some convenient methods for interacting with data for some frequently used mechanisms such as XML Documents or Database.
We can also customize these Adapters by simply inheriting from them and extending their behavior and that's what I've done here.
you can see our extended Adapter below :



private class MyAdapter extends ArrayAdapter {

private Activity context;

public MyAdapter(Result[] items){
super(MainActivity.this, R.layout.item,items);
this.context = MainActivity.this;
}

@Override
public View getView(int position,View convertView,ViewGroup parent){

LayoutInflater inflater= this.context.getLayoutInflater();
View row=inflater.inflate(R.layout.item, null);

TextView name = (TextView)row.findViewById(R.id.name);
TextView loc = (TextView)row.findViewById(R.id.location);
TextView phone = (TextView)row.findViewById(R.id.phone);

Result temp = (Result)getItem(position);

name.setText(temp.getName());
loc.setText(temp.getAddress());
phone.setText(temp.getPhone());

return row;
}

}




getView() method is our key method here, it is sent the position of a row in ListView and it's responsible to return a View Object representing that row which will be shown by ListView later. it is really cool because you can use
a View object and it means that you will be able to literally do whatever you want, i mean it would give you a great opportunity over how much you can customize your rows in ListViews.(we forget some basic concepts of OOP sometimes,
or should i say we underestimate how significant they could be, one of these basic concepts is Polymorphism...just look how nice it works here.... anyway just thought it'd be worthwhile to mention it ;) ).

Like any other View Objects we've created so far we can either use XML layout file or just hard code it. i used the first approach here, my layout file's name is item.xml and it looks like this :



<?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"
android:baselineAligned="true">




<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="5dip"
android:layout_gravity="left"
android:layout_width="wrap_content">

<TextView android:text="Name"
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="70dip"/>

<TextView android:text="Location"
android:id="@+id/location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="70dip"/>

<TextView android:text="PhoneNumber"
android:id="@+id/phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="70dip"/>


</LinearLayout>


</LinearLayout>



OK, let's get back to our getView() method that might seem a bit confusing....but it's not, believe me ;) .
all we need to do is to convert our layout file into a View Object, actually it's not a new thing...it's done in our all application but behind the scene. All we need to do is to get an instance of LayoutInflater object using getLayoutInfalter() method of Context class (Our Activity) and call inflate() method.once we have our view we can get the Result Object in that position and then fill our Textviews with appropriate data.

remember that each time that user does a search and there is any Result for that search we use the following code to renew our data in ListView :

listview.setAdapter(new MyAdapter(results));


I'm not sure whether it's a good way to do this though. ;)

The last thing I'm gonna talk about is menus and how to use them in our applications. we've got a menu with three options in our application but two options must be disabled unless we are in Result page, if user presses their phone menu button they will see something like this depending on which page they are currently in :











to achieve this we need to override three methods of Activity class which you can see below :




@Override
public boolean onCreateOptionsMenu(Menu menu) {

menu.add(0, 1, 0, "Show Saved entries");
menu.add(0, 2, 0, "Add to my contacts");
menu.add(0,3,0,"Save this entry");
return true;

}

@Override
public boolean onPrepareOptionsMenu(Menu menu){
//menu items are disable when we are in the main page...
for(int i=1;i<3;i++){
menu.getItem(i).setEnabled(!this.main);
}

return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item){

int id = item.getItemId();
this.selectedItem = (Result)view.getSelectedItem();

switch(id){

case 1 : showSavedData();
break;
case 2 : addToContact();
break;
case 3 : saveItem();
break;

default : assert false : "Invalid Options!";

}

return true;
}





I also want to have another menu which shows our options when user clicks on one of our result items in ViewList, we would need to be able to get notified when an item is clicked, ListView class has a setOnItemClickedListener() method which gets an instance of OnItemClickListener class this class has a callback method named onItemClicked(), you can see my implementation of this method here :



public void onItemClick(AdapterView adapter, View arg1, int position, long arg3) {

CharSequence[] options = {"ADD TO CONTACTS","SAVE THIS ENTRY"};

this.selectedItem = (Result)adapter.getItemAtPosition(position);

if(this.resultOptions == null){
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Options");
builder.setItems(options, new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub

if(which == 0)
addToContact();
else
saveItem();

dialog.cancel();
}
});

this.resultOptions = builder.create();
}

this.resultOptions.show();

}



so when user clicks on any item they will be shown something like this :






I will talk about WhitePageExtractor class that has been used to extract our data from www.whitepages.com.au and also I'm gonna figure out how to work with phone contacts and add a new contact in my next post...

1 comment:

Upcoming Android phones said...

just blogwalking and see your blog!
coolest android site