Search This Blog

Thursday, December 31, 2009

Android ViewFlipper and SlidingDrawer

In my last post i talked about android selector mechanism and how to customize default GUI components apperances. another issue with mobile phone applications is limited displaying space, i mean if your application wants to go a bit further than a basic , simple application, it is almost gonna be impossible to fit all GUI options and features in a relatively small displaying space of mobile phones.

as we've already talked about it, the first option to solve this sort of problems is Menus and dialogs which are pretty easy to use and simple, but what if you need something more than that with higher level of customizability, that's when ViewFlipper and SlidingDrawer come into play(although they could be used for other purposes as well), like menus and dialogs they enable us to have some views hidden and show them when they are requested or when it's appropriate.
I'm gonna add a ViewFlipper and SlidingDrawer to my last application.

first of all let's see what a ViewFlipper is, ViewFlipper is Actually a View container which can hold different Views, but it shows just one of those Views at a time and hide others, you can switch between views manually or automatically, most interesting thing about ViewFlipper is that it uses two different Animations for flipping between views, one is used for outgoing View and the other one for incoming View.
OK, here are some snapshots of what we are trying to achieve using a ViewFlipper:









There are two views between which we wanna flip, a ListView (Which we talked about it last time) and a simple view with a text and a button on it, When we press "Next" button our ListView will slide out and the other view will slide in and when "Go Back" button is pressed two views will be switched again.
our XML will be something like this :




<ViewFlipper android:id="@+id/flipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent">


<FrameLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="50dip">

<ListView android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:dividerHeight="0dip"
android:divider="@null"
android:listSelector="@drawable/list_selector"
android:layout_gravity="center" />

</FrameLayout>


<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/wood01"
android:padding="20dip"
android:layout_gravity="top"
android:layout_marginTop="50dip">

<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST"
android:layout_gravity="center"
android:padding="15dip"
android:textSize="22dip"
android:textColor="@color/white" />

<Button android:text="Go Back"
android:id="@+id/back_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />


</LinearLayout>



</ViewFlipper>





As you can see our ViewFlipper has two children, a FrameLayout containing the ListView and a LinearLayout containing a TextView and a Button. by default the first child is shown when application comes up for the first time.
setting Animation for our flipper is pretty easy and straigh forward, here's the code I've used :




this.flipper = (ViewFlipper)findViewById(R.id.flipper);

Animation s_in = AnimationUtils.loadAnimation(this, R.anim.slidein);
Animation s_out = AnimationUtils.loadAnimation(this, R.anim.slideout);
this.flipper.setInAnimation(s_in);
this.flipper.setOutAnimation(s_out);




and here are the content of slidein.xml and slideout.xml respectively :




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

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">

<translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="1800" />

</set>







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

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator">

<translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="1800" />

</set>




All you need to do to switch the showing view manually is to use showNext() and showPrevious() methods of ViewFlipper class.
Another predefined Widget for hiding stuff is SlidingDrawer and its name pretty much suggests what it does. what does a drawer do!? it has a handle which is used to drag the drawer container out...obviously ;)
I added a simple SlidingDrawer to my application and you can see how it looks like below :












First of all, I should say sorry for this wierd object I used for my drawer's handle ;) I couldn't find anything better!!
here is the XML which is being used to create what you saw above:




<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="230dip"
android:id="@+id/frameLayout"
android:layout_gravity="bottom">

<SlidingDrawer android:layout_height="wrap_content"
android:handle="@+id/handle"
android:content="@+id/content"
android:id="@+id/slide"
android:orientation="vertical"
android:layout_width="fill_parent">


<ImageView android:layout_width="55dip"
android:layout_height="55dip"
android:id="@id/handle"
android:src="@drawable/arrow" />


<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@id/content"
android:orientation="vertical"
android:background="@drawable/wood01"
android:padding="10dip">

<Button android:text="Test1"
android:id="@+id/Button01"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />

<Button android:text="Test2"
android:id="@+id/Button02"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />

<Button android:text="Test3"
android:id="@+id/Button03"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />


</LinearLayout>
</SlidingDrawer>
</FrameLayout>





SlidingDrawer tag has two important attributes, android:handle and android:content; these attributes are actually references to other views which will be rendered as our drawer's handle and content. as you can see here we have two child views with the same id as specified for android:handle and android:content.

That's it. we are now familiar with two other useful Android widgets...

10 comments:

DonF said...

Nice work, thanks

samhogy said...

If you wish to scroll both left and right in your ViewFlipper, you will need to do a bit of more animation xml than the example above.

In fact, you will need four files, which are identical to the two above, except for differing fromXDelta and toXDelta values:

In From Right FromX = 100%p ToX = 0

In From Left FromX = -100%p ToX = 0

Out To Right FromX = 0 ToX = 100%p

Out To Left FromX = 0 ToX = -100%p

I have touch control and buttons in my ViewFlipper, so I created a showNext() and a showPrevious() method.

The showNext() method has an IN animation = in from right, and an OUT animation = out to left.

Similarly, the showPrevious() method has an IN animation = in from left, and an OUT animation = out to right.

This gives a smooth transition which works in any direction.

Anonymous said...

sweet.. thanks Amir and samhogy. you guys just saved me a bunch of time.

here's the code i wrote based on samhogy suggestion.


ViewFlipper mViewFlipper = (ViewFlipper) findViewById(R.id.flipper);

private void showNext() {
mViewFlipper.setInAnimation(mActivity, R.anim.slide_in_from_right);
mViewFlipper.setOutAnimation(mActivity, R.anim.slide_out_to_left);
mViewFlipper.showNext();
}

private void showPrevious() {
mViewFlipper.setInAnimation(mActivity, R.anim.slide_in_from_left);
mViewFlipper.setOutAnimation(mActivity, R.anim.slide_out_to_right);
mViewFlipper.showPrevious();
}

Unknown said...

Thanks Amir, It is really such a nice work

Sticker Printing Los Angeles CA said...

I recently came across your blog and have been reading along.This post is well written and useful.I am hoping in future you will update with more interesting information.Thank you for sharing.

Phil Schloss said...

Thanks, I spent hours on this and could not get to look right, after reading this, took me 15 minutes to fix.
Phil

Aditya said...

Hi Amir,

A very helpful post.

Can you tell me how do I lock or disable clicks while the view flipping animation takes place.

I tried View.setEnabled(false) for the views that are being flipped but it didnt work. Do you have an efficient way of doing it.

Thanks.

Shubham said...

Hi to all, how to use SlidingDrawer top to bottom.

Invincible said...

Hey,
Its useful. I implemented also from your post.
But i want to implement touch and drag functionality in this viewflipper. When I will drag to left, then next screen should come from right to left and current screen should go from left to inside screen and vice-versa. How do i do that ?

jomy said...

@kishor...Use View pager for ur pupose.....