Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint

Nico Heid's picture

android
This article is a follow up of Use Android ActivityGroup within TabHost to show different Activity. As you probably noticed or read in the comments, the provided solution in the last article was less than ideal. Even though it does work, it uses multiple activies and therefor has a bigger memory consumption than necessary.

What happens when you use ActivityGroup with Tabhost

In the previous example we had one Activiy per tab. One tab was even holding two Activies and using ActivityGroup to switch between them. That's a total of five Activites that end up on the activity stack. Also the hierarchy was more nested than needed.

The improvement

So instead of using a Activity per Tab we can display a View in each. Thus we only need one Activity, all the events are caught by the class, so you need to find an ordered way of catching them. My example will implement the OnClickListener.

To keep the example short, we have two tabs. In the first one, there's a ViewFlipper which switches between two TextViews when clicked. In the second tab, there's just a bit of text and a button.

Here's the code:

  1. package com.unitedcoders.android.examples;
  2.  
  3. import android.app.TabActivity;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.TabHost;
  9. import android.widget.Toast;
  10. import android.widget.ViewFlipper;
  11.  
  12. public class Tabs extends TabActivity implements OnClickListener {
  13.  
  14.     Button doSomething;
  15.     TabHost tabHost;
  16.     ViewFlipper flipper;
  17.  
  18.     @Override
  19.     protected void onCreate(Bundle savedInstanceState) {
  20.         super.onCreate(savedInstanceState);
  21.         setContentView(R.layout.tablayout_1);
  22.  
  23.         doSomething = (Button) findViewById(R.id.btn_do_something);
  24.         doSomething.setOnClickListener(this);
  25.  
  26.         flipper = (ViewFlipper) findViewById(R.id.layout_tab_one);
  27.         flipper.setOnClickListener(this);
  28.  
  29.         tabHost = getTabHost();
  30.         tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("Tab1").setContent(R.id.layout_tab_one));
  31.         tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("Tab2").setContent(R.id.layout_tab_two));
  32.  
  33.         tabHost.setCurrentTab(0);
  34.  
  35.     }
  36.  
  37.     @Override
  38.     public void onClick(View v) {
  39.  
  40.         // show a toast in second tab
  41.         if (v == doSomething) {
  42.             Toast.makeText(getApplicationContext(), "doing something", Toast.LENGTH_SHORT).show();
  43.         }
  44.  
  45.         // toggle TextView in first tab
  46.         if (v == flipper) {
  47.             flipper.showNext();
  48.         }
  49.  
  50.     }
  51.  
  52. }

and the layout that goes with it:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
  3.         android:id="@android:id/tabhost" android:layout_width="fill_parent"
  4.         android:layout_height="fill_parent">
  5.  
  6.         <LinearLayout android:orientation="vertical"
  7.                 android:layout_width="fill_parent" android:layout_height="fill_parent">
  8.                 <TabWidget android:id="@android:id/tabs"
  9.                         android:layout_width="fill_parent" android:layout_height="wrap_content" />
  10.                 <FrameLayout android:id="@android:id/tabcontent"
  11.                         android:layout_width="fill_parent" android:layout_height="fill_parent">
  12.  
  13.  
  14.                         <ViewFlipper android:id="@+id/layout_tab_one"
  15.                                 android:layout_width="fill_parent" android:layout_height="fill_parent">
  16.  
  17.                                 <TextView android:id="@+id/tabone1" android:layout_width="fill_parent"
  18.                                         android:layout_height="fill_parent" android:text="this is a tab one" />
  19.                                 <TextView android:id="@+id/tabone2" android:layout_width="fill_parent"
  20.                                         android:layout_height="fill_parent" android:text="this is the other tab one" />
  21.  
  22.                         </ViewFlipper>
  23.  
  24.  
  25.  
  26.                         <LinearLayout android:id="@+id/layout_tab_two"
  27.                                 android:orientation="vertical" android:layout_width="fill_parent"
  28.                                 android:layout_height="fill_parent">
  29.                                 <TextView android:id="@+id/textview2" android:layout_width="fill_parent"
  30.                                         android:layout_height="wrap_content" android:text="this is a tab two" />
  31.                                 <Button android:id="@+id/btn_do_something" android:text="do something"
  32.                                         android:layout_width="fill_parent" android:layout_height="wrap_content" />
  33.  
  34.                         </LinearLayout>
  35.  
  36.                 </FrameLayout>
  37.         </LinearLayout>
  38.  
  39.  
  40. </TabHost>

From this UI you can use AsyncTask to do your processing and refresh the UI. This will keep your number of Activities and the memory consumption low.

As a little bonus, here are the screenshots of the hierachy view for the
current example and the previous one.

The code is in the UCdroid project on github. You can run it on your device or emulator.

Comments

Use Android ActivityGroup within TabHost to show different A's picture

[...] there is an updated version to this article with some improvements. please also read: Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint. [...]

 Twitter Trackbacks for Android ViewFlipper within TabHost f's picture

[...] Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint | u... united-coders.com/nico-heid/android-viewflipper-w...-for-tabs-with-different-views-and-better-memory – view page – cached Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint Tweets about this link [...]

Android UI testing with robotium | united-coders.com's picture

[...] will base this post on the last article: Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint, where we had a TabHost and a ViewFlipper. To test that our example is still working, we have to [...]

reddy's picture

Thanks for your post.

As we used in activitygroup can we use different activities in viewflipper.

For example in Tab A , I have a button if i click on button am moving to other activity.
and in that activity if i click on button than i have to move to other activity, i mean to say is can we use intents.

I hope u r clear with my problem.

Please do the needful.

Thanks.

Nico Heid's picture

yes that's possible.
use your button to start a new intent. all you need to do is catch the button by its id and start a new intent.

like this:

  1.    @Override
  2.     public void onClick(View v) {
  3.  
  4.         // start new intent on button clicked
  5.         if (v == yourButton) {
  6.             Intent intent = new Intent(context, YourIntent.class);
  7.             startActivity(intent);
  8.         }
  9. }

Anonymous's picture

but ,if we start a new activity ,the Tab Layout is no longer visible again,right?

Nico Heid's picture

yes, the idea is, as long as you want to stay in the tab layout, just use this one activity.
but if you really have to move to another activity, you can still use the same layout and use inheritance to simplify. but i do not see a point where this would be necessary at the moment. maybe you have something more specific in mind.

googlelight's picture

Hi , thanks a lot for your tutorial , it has been verry helpful ,however i 'm kind stuck , i'am new to android and i'am trying to make a tabhost inside a view flipper but it can't seem to work , i 've tried so many things without any success ;

if u can give me an example using a tabhost inside a viewflipper i would be verry greatful ;

marsbear's picture

You can implement startActivityFromChild() in your ActivityGroup which enables you to intercept all Intent-calls from activities within your ActivityGroup. This method is pretty straight forward. You have to manually keep track of your history tho.

Best regards
Marc

marsbear's picture

Forgot to mention that you can refire intercepted intents inside your ActivityGroup so that they will display in yout tab-window, too. Maybe you should check for the intent-flag new-task as you usually want to let them break out your tab-window (e.g. if you open the brwoser from within your app).

ramisetty srinivasa rao's picture

i want to get the tab screen after button click of first screen

Nico Heid's picture

TabHost has the method
setCurrentTab
so you can switch to a different tab after the event.

Anonymous's picture

How are we supposed to manage StartActivityForResult by using ActivityGroups in Tab??

Nico Heid's picture
martin's picture

I followed your improved version, but now I'm stuck again. How can I use ListView in one of the tabs when everything is in one class and it extends TabActivity, and I also need to extend ListActivity to be able to use a List. As you know, I can only extend one class at the time. How can I solve this?

Thanks in advise!
(Please send me an e-mail when you replay :-)

Vedovelli's picture

=D

ezhil's picture

it so useful and clearly thanks

batur 's picture

Hi i am oldies programmer but new for android. I need to call some child view from the main xml's layout. For example you have button on your main page when you click to button i wan't to open another view let say dateview. and you have another button on this page. Question is where can i put Onclik listener for this button. Also i need when click to last button active view must be cloase and back to the main page. Thank you very much.

Anonymous's picture

I am gone through your code
I am facing error..if I want to display Text name that we used with the viewflipper individual .

you have , I already posted this question on stackoverflow .if possible please guide me for that.

http://stackoverflow.com/questions/9799189/toast-string-display-object-i...

Alpha's picture

Hi , I need your Help , I have a viewFlipper in ActivityGroup that implement OnGestureListener , but onFling is not working for me , because of tabhoust i think ! .