Search This Blog

Thursday, December 10, 2009

WhitePage Application_Part One

Before starting i gotta say something, Android is amazing...i mean more you work with it more you understand how well designed this Google's creature is. i had a painful experience with J2ME a couple of years ago and i cannot forget how frustrating it was. although i am a Java lover, i think we should admit that there is no light at end of J2ME tunnel.
Android on the other hand is really fascinating; beautiful API, comprehensive documentation and snappy simulator; what else would someone expect from a good framework?

Ok...let's get down to our business, in my last post I talked about html data extraction and said I would develope an application to do what exactly www.whitepages.com.au is doing...I have done it and I'm gonna be talking about this application in a few next posts.
I have examined some of basic android GUI capabilities such as menus,dialogs,List view and simple animations which will be discussed in this post and next post, remember that codes that are provided here should not be considered as the best possible way to do stuff...they are just examples for me and you to get familiar with this whole thing...

anyway,our application main page looks like this :













if you wanna have a good looking GUI in both portrait and landscape modes, there are two possibilities, either design your layout in a flexible fashion to support both modes or use a seperate layout file for each mode(default layout directoryfor portrait mode and "layout-land" directory which will be used for landscape mode, so if you need a different layout for
landscape mode just put your landscape specific designed file in "layout-land" instead of "layout" directory).
I used a single layout file since our GUI is simple and i could manage to have a dynamic GUI using a single layout file :



<?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/mainLayout"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="true"
android:background="@color/black">



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

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

<EditText android:text=" "
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="400dip"
android:gravity="top"
android:minWidth="230dip"></EditText>


</LinearLayout>

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

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

<EditText android:text=" "
android:id="@+id/location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="400dip"
android:gravity="top"
android:minWidth="230dip"></EditText>


</LinearLayout>



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

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

<EditText android:text=" "
android:id="@+id/initial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="400dip"
android:gravity="top"
android:minWidth="230dip"></EditText>


</LinearLayout>


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

<Button android:text="@string/searchBtn"
android:id="@+id/search"
android:layout_height="wrap_content"
android:gravity="center_horizontal|center"
android:layout_width="150dip"></Button>

</LinearLayout>

</LinearLayout>

</LinearLayout>




when user presses search button, if our thread cannot find any result, a dialog will be shown to user telling him no result have been found :



Using dialogs in Android is pretty easy and straight forward, all you need to do is to use AlertDialog.Builder class to create
your Dialog instance, once you have your Dialog instance created, you can show it or hide it whenever you want, below is
our code for our dialog you just saw :




if(results == null || results.length == 0){
if(alertDialog == null){
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

builder.setMessage("No Result Could be found").setNeutralButton("OK",
new DialogInterface.OnClickListener() {


@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}

});

MainActivity.this.alertDialog = builder.create();

}

alertDialog.show();





you can also use setPositiveButton() or set NegativeButton() just like setNeutralButton() if you need to have yes/no or agree/disagree buttons.


Obviously there will be a time gap between user presses the search button and when the data extraction process gets finished because we are getting our data using network. it is usually a good practice to show users that something is happening behind the scene specially when delay is likely to be more than 1 or 2 seconds...thankfully Android has taken care of this issue... when search button is pressed we will start our thread to extract data and then we simply
use following code :



ProgressDialog.show(this, "","Please wait...", true);



show() method returns an instance of ProgressDialog class which can be used to interact with the showing dialog, in this case we will call cancel() method later when the process finishes.

after calling show() method our application will be looking like this :




Fair enough, we have already handled the situation where there is no result, but what happens when there is some results?
I've used Android ListView to show the result to users :




I'm gonna talk about ListView class and how to use it in a customized manner next time. what I'm gonna talk about right now is how to use Animation in android,it's not gonna be comprehensive but it is a simple example which has helped me to have a better understanding of Animation handling mechanism in Android and hopefully it will be helpful for you as well.
Actually when search button is pressed current page(containing Text Feilds and search button) does not just simply replace by result page but it will start to rotating and shrinking until it completely disappears and then Result page
gradually replaces previous page...














Initially i thought it was gonna be so tricky and chalenging given the fact that this sort of stuff had always been a big headache for me but once again I impressed by Android capabilities and how well this API has been designed.
one of the most interesting things which i hadn't realized before but we all gotta know is startAnimation() method of View class. yes...simple as this, all Views have a startAnimation() method which has an Animation Object as input parameter and can be called whenever you want to apply an animation on a view.
you can create animation objects problematically or using XML file, I've used the latter.
here is the XML file which is used to animate our application's main page after search button get pressed :



<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="0.8"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="500" />


<set android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="0.8"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="700"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-60"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="700" />
</set>
</set>



as you can see we used three different animation effects, two Scale animation and one Rotate Animation, there are two more animation types that can be used as well, Alpha animation (<alpha> tag) and Translation animation (<translate> tag). you can use <set> tags to combine two or more animation instances, you can also use nested <set> tags like I have used in this example(actually i sorta pinched this XML file from Android API Demo ;) ).
first our view gets shrunk from its original size (1.0X,1.0X) to (0.8X,0.6X), it will take 500 milliseconds to finish, then after 200 milliseconds shrunk view starts to rotating and shrinking simultaneously until it disappears (0.0X.0.0X).

for Resultpage i used a simple animation :



<?xml version="1.0" encoding="utf-8"?>


<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="0.1"
android:toXScale="1.2"
android:fromYScale="0.1"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:duration="800"
android:fillBefore="false" />

</set>



and here is the code that has been used to run these two animation and replace main view by result view :




LinearLayout LL = (LinearLayout) findViewById(R.id.mainLayout);
Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.effect);
Animation reverse = AnimationUtils.loadAnimation(MainActivity.this,R.anim.reverse);

LL.startAnimation(animation);
resultPage.startAnimation(reverse);


animation.setAnimationListener(new AnimationListener() {

@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub

}

@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub

}

@Override
public void onAnimationEnd(Animation animation) {

setContentView(resultPage);
main = false;

}
});



No comments: