RSS

Android : Tabs + ViewPager (Swipe-able Tabs, FTW)

13 Oct

In my previous two posts, I explained how you would implement Tabs using Fragments and then how to implement page swiping using ViewPager.  In this post, I’ll bring those two nuggets together and show you how to implement Swipe-able Tabs (i.e switch between tabs using the swipe gesture).

* Caveat Alert * At the time of this posting, there is no way of implementing MapView as a fragment, which may put a spanner in the works if you’re thinking about using this UI pattern with a MapView.

Requirements

To implement a Tabs & ViewPager, using fragments on devices running Android 2.1 or higher, you’ll need to include the Android Compatibility library.  In my example, I’m using Compatibility library v4.

Step-by-step

  1. Define the Tab ViewPager layout
  2. Define the PagerAdapter
  3. Define the Tab FragmentActivity

The Code

The Tab ViewPager layout

The Tab ViewPager layout (tabs_viewpager_layout.xml) declares a TabHost and child TabWidget views as per normal.  For this implementation, instead of having the dummy FrameLayout to hold the content, we define the ViewPager (android.support.v4.view.ViewPager)

<?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">
	<TabHost
	    android:id="@android:id/tabhost"
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent"
	    >
	    <LinearLayout
	        android:orientation="vertical"
	        android:layout_width="fill_parent"
	        android:layout_height="fill_parent"
	        >
	        <TabWidget
	            android:id="@android:id/tabs"
	            android:orientation="horizontal"
	            android:layout_width="fill_parent"
	            android:layout_height="wrap_content"
	            android:layout_weight="0"
	            />

	        <FrameLayout
	            android:id="@android:id/tabcontent"
	            android:layout_width="0dp"
	            android:layout_height="0dp"
	            android:layout_weight="0"/>

	        <android.support.v4.view.ViewPager
			  	android:id="@+id/viewpager"
			  	android:layout_width="fill_parent"
			 	android:layout_height="0dp"
			 	android:layout_weight="1"
			  	/>
	    </LinearLayout>
	</TabHost>
</LinearLayout>

Define the PagerAdapter

As explained in the previous post, Page Swiping using ViewPager, the PagerAdapter is responsible for creating/returning the appropriate Fragment to the ViewPager.  The declaration of PageAdapter is unchanged from the previous post.

/**
 *
 */
package com.andy.fragments.viewpager;

import java.util.List;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

/**
 * The <code>PagerAdapter</code> serves the fragments when paging.
 * @author mwho
 */
public class PagerAdapter extends FragmentPagerAdapter {

	private List<Fragment> fragments;
	/**
	 * @param fm
	 * @param fragments
	 */
	public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
		super(fm);
		this.fragments = fragments;
	}
	/* (non-Javadoc)
	 * @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
	 */
	@Override
	public Fragment getItem(int position) {
		return this.fragments.get(position);
	}

	/* (non-Javadoc)
	 * @see android.support.v4.view.PagerAdapter#getCount()
	 */
	@Override
	public int getCount() {
		return this.fragments.size();
	}
}

Define the Tab FragmentActivity

The Tab FragmentActivity is a modified version Tab FragmentActivity I posted about in, Tabs, The Fragment Way. Thankfully, using ViewPager requires less code =)

*Disclaimer: The redundant lines of code are there to illustrate the minimal amount of changes required to implement view paging from the stock Tab implementation*

Change 1: As per the normal initialisation of Tabs, we create Tahhost.TabSpec instances for each tab.  In this implementation, we simple just add it to the TabHost (line 139) without having to detach fragments.

Change 2: Initialise the ViewPager. From line 099, we instantiate the Fragments and pass them to the ViewPager via the PagerAdapter. The order that the Fragments are supplied in the List will determine their tab order.

Change 3: Tab FragmentActivity to implement ViewPager.OnPageChangeListener interface. In order to handle page “swipe” events, our Tab FragmentActivity needs to implement the ViewPager.OnPageChangeListener interface. For our purpose we only really need to implement the onPageSelect() method (Line 168). Simply, when the page is selected (paged), it’s associated Tab is selected.

Change 4: Modify the onTabChanged() method. Similarly to Change 3, when a tab is select (and therefore becomes selected), we set the appropriate Fragment via the ViewPager mViewPager (Line 148).

package com.andy.fragments.tabs;

import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;

import com.andy.R;
import com.andy.fragments.viewpager.PagerAdapter;

/**
 * The <code>TabsViewPagerFragmentActivity</code> class implements the Fragment activity that maintains a TabHost using a ViewPager.
 * @author mwho
 */
public class TabsViewPagerFragmentActivity extends FragmentActivity implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {

	private TabHost mTabHost;
	private ViewPager mViewPager;
	private HashMap<String, TabInfo> mapTabInfo = new HashMap<String, TabsViewPagerFragmentActivity.TabInfo>();
	private PagerAdapter mPagerAdapter;
	/**
	 *
	 * @author mwho
	 * Maintains extrinsic info of a tab's construct
	 */
	private class TabInfo {
		 private String tag;
         private Class<?> clss;
         private Bundle args;
         private Fragment fragment;
         TabInfo(String tag, Class<?> clazz, Bundle args) {
        	 this.tag = tag;
        	 this.clss = clazz;
        	 this.args = args;
         }

	}
	/**
	 * A simple factory that returns dummy views to the Tabhost
	 * @author mwho
	 */
	class TabFactory implements TabContentFactory {

		private final Context mContext;

	    /**
	     * @param context
	     */
	    public TabFactory(Context context) {
	        mContext = context;
	    }

	    /** (non-Javadoc)
	     * @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)
	     */
	    public View createTabContent(String tag) {
	        View v = new View(mContext);
	        v.setMinimumWidth(0);
	        v.setMinimumHeight(0);
	        return v;
	    }

	}
	/** (non-Javadoc)
	 * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)
	 */
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Inflate the layout
		setContentView(R.layout.tabs_viewpager_layout);
		// Initialise the TabHost
		this.initialiseTabHost(savedInstanceState);
		if (savedInstanceState != null) {
            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
        }
		// Intialise ViewPager
		this.intialiseViewPager();
	}

	/** (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)
     */
    protected void onSaveInstanceState(Bundle outState) {
        outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
        super.onSaveInstanceState(outState);
    }

    /**
     * Initialise ViewPager
     */
    private void intialiseViewPager() {

		List<Fragment> fragments = new Vector<Fragment>();
		fragments.add(Fragment.instantiate(this, Tab1Fragment.class.getName()));
		fragments.add(Fragment.instantiate(this, Tab2Fragment.class.getName()));
		fragments.add(Fragment.instantiate(this, Tab3Fragment.class.getName()));
		this.mPagerAdapter  = new PagerAdapter(super.getSupportFragmentManager(), fragments);
		//
		this.mViewPager = (ViewPager)super.findViewById(R.id.viewpager);
		this.mViewPager.setAdapter(this.mPagerAdapter);
		this.mViewPager.setOnPageChangeListener(this);
    }

	/**
	 * Initialise the Tab Host
	 */
	private void initialiseTabHost(Bundle args) {
		mTabHost = (TabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup();
        TabInfo tabInfo = null;
        TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab1").setIndicator("Tab 1"), ( tabInfo = new TabInfo("Tab1", Tab1Fragment.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab2").setIndicator("Tab 2"), ( tabInfo = new TabInfo("Tab2", Tab2Fragment.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab3").setIndicator("Tab 3"), ( tabInfo = new TabInfo("Tab3", Tab3Fragment.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        // Default to first tab
        //this.onTabChanged("Tab1");
        //
        mTabHost.setOnTabChangedListener(this);
	}

	/**
	 * Add Tab content to the Tabhost
	 * @param activity
	 * @param tabHost
	 * @param tabSpec
	 * @param clss
	 * @param args
	 */
	private static void AddTab(TabsViewPagerFragmentActivity activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
		// Attach a Tab view factory to the spec
		tabSpec.setContent(activity.new TabFactory(activity));
        tabHost.addTab(tabSpec);
	}

	/** (non-Javadoc)
	 * @see android.widget.TabHost.OnTabChangeListener#onTabChanged(java.lang.String)
	 */
	public void onTabChanged(String tag) {
		//TabInfo newTab = this.mapTabInfo.get(tag);
		int pos = this.mTabHost.getCurrentTab();
		this.mViewPager.setCurrentItem(pos);
    }

	/* (non-Javadoc)
	 * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)
	 */
	@Override
	public void onPageScrolled(int position, float positionOffset,
			int positionOffsetPixels) {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageSelected(int)
	 */
	@Override
	public void onPageSelected(int position) {
		// TODO Auto-generated method stub
		this.mTabHost.setCurrentTab(position);
	}

	/* (non-Javadoc)
	 * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)
	 */
	@Override
	public void onPageScrollStateChanged(int state) {
		// TODO Auto-generated method stub

	}
}

The Result

 
128 Comments

Posted by on October 13, 2011 in Android

 

Tags: , , , ,

128 responses to “Android : Tabs + ViewPager (Swipe-able Tabs, FTW)

  1. Jeff Linwood (@jefflinwood)

    October 15, 2011 at 09:38

    It looks like there’s a workaround for using MapView within a Fragment – https://github.com/petedoyle/android-support-v4-googlemaps

    I’ll probably try this out a little later. Thanks for the great series of blog posts about Fragments and View Pager!

     
    • mitchwongho

      October 15, 2011 at 14:22

      Hi Jeff.

      Thanks for visiting. I’m glad you found the posts useful =)

      Also, thanks for the project reference. I do hope that the Google Android team consider giving the MapView the Fragment treatment

       
      • Akinsete Sunday

        June 26, 2012 at 08:34

        I tried this but am getting some errors. Please help..Maybe you need to paste codes for Tab1Fragment.class,Tab2Fragment.class as well

         
  2. Jeff Linwood (@jefflinwood)

    October 15, 2011 at 16:02

    I actually ran into some really strange class loader issues with Dalvik when I used the precompiled lib from that page last night. Replacing it with the stock compatibility library made the issues go away, so I think I may need to try building it from source.

    Yes, your posts are the best I’ve seen on fragments and View Pager!

     
  3. Mike Stone

    October 17, 2011 at 21:48

    Thanks a lot. This helped me get to where I am…multiple tabs with swipe support!

    I have a quick question though. The transition or scrolling while swiping isn’t the smoothest. Do you know of a way I can make this better?

    Thanks
    Mike

     
    • mitchwongho

      October 18, 2011 at 00:38

      Hi Mike,

      Thanks for visiting. I’m glad you’ve found the posts helpful.

      Are you testing on an HTC by any chance? I suspect that the Sense UI has something to do with it as I’ve heard similar concerns in the past.

      I’m running this demo on a Huewei 858 Android 2.2 phone (a real low end device) and the transitions are smooth. In other words, I don’t have a solution for you 🙂

      Please let us know if you do resolve the issue.

       
      • Mike Stone

        October 18, 2011 at 00:43

        Thanks for the response.

        I am running on a Nexus S. currently running 2.3.1.

        I will keep you up to date with my findings!

        Thanks again.

        Mike

         
  4. Alex

    November 8, 2011 at 12:16

    Hi,

    thanks alot for that post helped me alot.
    I have one Question.
    I have build an app with 3 Tabs like in your tutorial.
    On tab1 there is a listview filled by async task.
    On tab2 is an streight forward linearlayout some images an so on and
    on the 3rd tab there is an expandableListview. All works fine together.

    My App starts on tab2 causing tab1 and 3 to call onviewcreate. But when I swipe from tab2 to tab1, tab 3 calls onviewdestroy. When I swipe back to tab2, tab3 calls onviewcreate again. The same with tab1 when i swipe to tab3.
    So every time the data gets downladed by that async task.

    My Question is there a way to once load the tabs for the runtime of the app. And dont recreate every time?
    Sure I could use database to store the data but even then the tabs gets recreated over and over again. I want that to disable. Is that even posible?

    Appriciate your answer.

    Thanks
    Alex

     
    • Mike Stone

      November 9, 2011 at 18:24

      ViewPager.setOffscreenPageLimit using the compatilibty library v4

      See: http://developer.android.com/sdk/compatibility-library.html
      Look under ViewPager
      “Added support to control how many pages are kept to either side of the current page.”

       
      • mitchwongho

        November 10, 2011 at 09:27

        Thanks for the reference, Mike.

        At some point, you’ll need to save the state of the Fragment (either for orientation changes or when your app gets moved to the background).

        Consider using FragmentStatePagerAdapter instead.

         
      • Alex

        November 10, 2011 at 10:53

        Thanks for your reply Mike.
        The expirience of using the app is much better now.

        Thanks.

         
      • aimango

        January 25, 2012 at 03:05

        Hey, for some reason I’m not able to use setOffscreenPageLimit with my ViewPager. I have revision 6 for the support package, though. Do you know how to fix this problem?

        Thanks!

         
      • aimango

        January 25, 2012 at 03:12

        Ignore my last comment – I figured it out!

         
    • Fahad

      August 5, 2014 at 06:31

      Hie Alex,

      I also want to include expandable list on tabs, can you please help me in this regard, I am badly stuck.

       
  5. pop

    November 9, 2011 at 13:48

    Can you upload source code ?
    I tried but i always showed “force close”.
    Many thanks to you 🙂

     
  6. Chan

    November 13, 2011 at 17:02

    @mitchwongho: Could you upload the source again? The link was broken. And thanks for a great tut.

     
  7. syrine

    November 14, 2011 at 16:35

    hey
    awesome tutorial it helped me a lot , but i’ve noticed that on orientation changed it provoke an NPE :/ it can’t find the current tab

    11-14 15:27:10.231: E/AndroidRuntime(13788): Caused by: java.lang.NullPointerException
    11-14 15:27:10.231: E/AndroidRuntime(13788): at com.some.Thing.other.Activities.onTabChanged(MyTabActivity.java:153)
    11-14 15:27:10.231: E/AndroidRuntime(13788): at android.widget.TabHost.invokeOnTabChangeListener(TabHost.java:378)
    11-14 15:27:10.231: E/AndroidRuntime(13788): at android.widget.TabHost.setCurrentTab(TabHost.java:363)
    11-14 15:27:10.231: E/AndroidRuntime(13788): at android.widget.TabHost.setCurrentTabByTag(TabHost.java:285)
    11-14 15:27:10.231: E/AndroidRuntime(13788): at com.some.Thing.other.Activities.MyTabActivity.onCreate(MyTabActivity.java:84)

    i’m i the only one who have this problem?

     
  8. syrine

    November 14, 2011 at 17:04

    the problem was this couple of lines :/
    081 if (savedInstanceState != null) {
    082 mTabHost.setCurrentTabByTag(savedInstanceState.getString(“tab”)); //set the tab as per the saved state
    083
    }
    i’ve commented it and it’s ok now ..i don’t know if it’s a good idea to ignore this lines (you can tell me) but it solved my problem 😉

     
    • mitchwongho

      November 15, 2011 at 10:57

      Hi,

      Thanks for visiting. One thing I haven’t implemented in the examples is saving state. This is what is causing the Exception. What you’ll need to do, is save the active Fragment in the bundle, and then read it back to switch to the appropriate Fragment

       
      • blubberheld

        June 25, 2012 at 16:12

        Hi,
        i know it’s been a while.
        But i don’t get it to fix the rotation problem.

        could you please help me

         
  9. AKeyWeb

    November 15, 2011 at 10:33

    What would be the easiest way to remove a tab, add new ones and replace the fragment within a tab both at the end and at a specific position?

     
    • mitchwongho

      November 15, 2011 at 11:24

      Hi,

      Thanks for visiting.

      That is a great questions! I don’t believe there is a simple way. As a follow up from another reader asking how to implement a Carousel-style of ViewPager, I discovered that the FragmentManager tags each Fragment with it’s position in the deck, so manipulating the order and behaviour of the FragmentManager is not a simple task.

      One option is manage different views based on the Activity’s context (i.e inflate a different layout based on state or context). Changing the Tab’s label should be straight forward)

      Let us know how if you find another way.

       
  10. Newby1

    November 23, 2011 at 16:03

    Mitch,

    I am just learning writing for android with Eclipse. I have your example running in the emulator at this time. My question is this: If I want to add a ListView into the Tab1Fragment is it done within a Tab1Fragment class event or should a ListFragment class be created and then called from the Tab1Fragment class?

    Great tutorial.

     
    • mitchwongho

      November 23, 2011 at 16:33

      Hi,

      You’d create layout that declares a ListView (e.g res/layout/mylist_layout.xml with id=mylist_layout) and then inflate that layout in the onCreate() method of Tab1Fragment i,e

      View view = inflater.inflate(R.layout.mylist_layout, container, false);

       
  11. CuriousCursor

    November 25, 2011 at 03:05

     
  12. doctor

    December 20, 2011 at 18:22

    hello, i test Force close. this my logcat :

    12-20 23:19:58.020: E/AndroidRuntime(25176): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tab.pager/com.tab.pager.TabFragment}: java.lang.ClassCastException: com.tab.pager.Tab1Fragment
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1768)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1784)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread.access$1500(ActivityThread.java:123)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.os.Handler.dispatchMessage(Handler.java:99)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.os.Looper.loop(Looper.java:130)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread.main(ActivityThread.java:3835)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at java.lang.reflect.Method.invokeNative(Native Method)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at java.lang.reflect.Method.invoke(Method.java:507)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at dalvik.system.NativeStart.main(Native Method)
    12-20 23:19:58.020: E/AndroidRuntime(25176): Caused by: java.lang.ClassCastException: com.tab.pager.Tab1Fragment
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.support.v4.app.Fragment.instantiate(Fragment.java:377)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.support.v4.app.Fragment.instantiate(Fragment.java:352)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at com.tab.pager.TabFragment.intialiseViewPager(TabFragment.java:102)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at com.tab.pager.TabFragment.onCreate(TabFragment.java:85)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    12-20 23:19:58.020: E/AndroidRuntime(25176): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1722)

    thanks before. 😀

     
    • mitchwongho

      December 20, 2011 at 21:48

      Hi,

      Are you getting this when you run the reference code? Else, you can post your code and we can have a look to see where the error is originating from.

       
  13. Stalski

    December 31, 2011 at 22:38

    This post is really awesome as well (I read the previous ones too, and tried them out). This swipe behavior is just what I was looking for. I don’t know if this is advanced or not, but I can assure your that this is clear to a non-java programmer who tries to create his first android app.

    Great you shared this with us.

     
  14. Madhav Palshikar

    January 2, 2012 at 10:49

    Nice tutorial…
    how to add button onclick method in viewpager…? plz help

    Thank you for tutorial.

     
    • mitchwongho

      January 3, 2012 at 08:45

      Hi Madhav,

      There are two ways to handle Button onClick events wrt Fragments:
      1. Events are received by the FragmentActivity, so you’ll need to implement the event handler in the FragmentActivity implementation and then delegate it back to the active Fragment, or

      2. in the Fragment that contains the Button, find the Button component (using findViewById()) and register your event handler using the Button.onClick() method.

       
  15. frontine

    January 18, 2012 at 06:46

    hi mitchwongho
    i’m implemented listview data from json in this tutorial. i make 4 tabs, listview i put in first tab, then i choose third tab and then back to first tab, listview reload again but if i choose beside first tab, firsttab (listview not reload).
    can you help me how to solved?
    if can i send my project to your email.
    sorry for my bad english,
    i’m from Indonesia.hehe

     
  16. Sohayb

    January 18, 2012 at 14:35

    Hi; this is rly nice. But i need help; how to replace the fragments by FragmentActivities and maintain the work of the viewPager? whenever i try to replace fragments by FragmentActivities the tabs display nothing at all!!

     
  17. Sushil

    February 3, 2012 at 12:51

    Hi Mitchwongho,

    Thank you for your very impressive tutorial. I downloaded your code from git and tried to run it on my Nexus S and Galaxy S2. In both the phones I am not able to see the tabs. It is just working as your page viewer tutorial where I can only swipe among 3 pages. The tabs are not at all visible. Can you please help.

    Thanks,
    Sushil

     
  18. Sushil

    February 3, 2012 at 13:38

    Hi,

    I got the reason why tab was not coming for me. I had to change the AndroidManifest file to launch correct activity. Thanks anyway.

    Cheers,
    Sushil

     
  19. pankajchunchun

    February 14, 2012 at 13:18

    Hi mitchwongho I have implemented the same code as it is. I am getting NPE when orientation change and when onpouse method called. Any thing wrong?

     
  20. tadinesh

    February 15, 2012 at 11:19

    Hi,
    If I rotate this app it force close 😦 what to do?

     
  21. ZonedCode Media

    February 23, 2012 at 01:35

    Wow! Thank you so much! I spent some three days trying to get my tabs to swipe. I tried everything, including recreating the sample code in my own project. Nothing worked, until this! I spent five minutes just dancing around my house when it worked because I was so happy/relieved (thank goodness I was alone).
    Thank you, again!

     
  22. Paulo Ricardo

    March 16, 2012 at 14:12

    Hello Mitchwongho,

    Could you tell me if there is any way to change fragment within each tab? I tried to do with your example, but the fragment does not appear.

    FragmentTransaction getFragmentManager ft = (). BeginTransaction ();
    ft.replace (R.id.viewpager, new TabFragmen1t ());
    ft.setTransition (FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.addToBackStack (null);
    ft.commit ();

     
  23. Andy

    March 19, 2012 at 14:49

    i copied ur code as it is i m new android developer i m getting error in tab1Fragment.class i m not understanding what this class means is it extended to activity

     
  24. Vinc3nt

    March 29, 2012 at 17:02

    Thank u for this post. I have 5 Tabs and when i swipe very fast, the tabs skips for example from tab 2 to tab 4. Do you know how to solve this problem?

     
  25. Ammon R.

    March 31, 2012 at 23:32

    Hey!

    First off great tutorial!! I’m new to programming and this may be a stupid question but I’ve been searching for the solution everywhere with no luck. i’m getting this error

    The constructor MyPageAdapter(FragmentManager, List) is undefined

    Here is my code

    List fragments = new Vector();
    fragments.add(Fragment.instantiate(this, article1.class.getName()));
    fragments.add(Fragment.instantiate(this, article2.class.getName()));
    fragments.add(Fragment.instantiate(this, article3.class.getName()));
    this.mPagerAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);

    any ideas on how to fix this error i would very much appreciate!!

    Thanks again!

     
  26. stevemuss

    April 16, 2012 at 14:07

    How do I replace one of the fragments?

     
  27. stevemuss

    April 16, 2012 at 14:09

    How do I replace a fragment?

     
  28. Glenn

    April 18, 2012 at 10:03

    hi there mitchwongho,

    A very nice tutorial.. been reading a lot about fragments.. I have a few questions though

    1. how to include a drawable/picture on top of the tab names/items
    2. how to implement an two activity with a tab, somewhat look like this:
    tab1 / tab2 / tab3
    / /
    act1 / act2/act4 / act3

    * like for instance, there’s two activity (act3 & act4) inside tab2.. by showing the (act4) you put/push a button2 and put/push button1 to show act3.

    hope you can give me some insights on this. thank you

     
    • Glenn

      April 18, 2012 at 10:12

      sorry.. what i mean is.. ** two activity within a tab act2/act4**

      then show act4 by pressing button2—-
      and show act2 by pressing button1—–

      i happened to observed this on TED 1.0.5 app..

      thanks once again…

       
  29. fullbugz

    May 2, 2012 at 09:08

    @mitchwongho
    this is usefull tutorial. thanks
    I have a question?
    If i have 10 tab in the tab control? how do i page those tabs too? i mean we can slice left or right on the tab control to select this tab? it look like the listview, but oriented to horizontal
    thanks

     
  30. slippyboy

    May 3, 2012 at 05:13

    Reblogged this on Slippyboy's Blog.

     
  31. newjay08

    May 10, 2012 at 11:00

    Hi, I got a “NullPointerException” here:

    mTabHost = (TabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup();

     
  32. newjay08

    May 10, 2012 at 11:02

    Hi! I got a “NullPointerException” here:

    mTabHost = (TabHost)findViewById(android.R.id.tabhost);
    mTabHost.setup();

     
    • newjay08

      May 10, 2012 at 11:06

      I solved it. Nice tutorial.

       
  33. newjay08

    May 11, 2012 at 05:06

    Hi, can you help me with this one. I only one Fragment class instead of three. The problem is I can’t set programmatically the content of my fragment class. Here’s my changes from your code.

    ***TabsViewPagerFragmentActivity****

    Bundle bundle1 = new Bundle();
    Bundle bundle2 = new Bundle();
    Bundle bundle3 = new Bundle();
    bundle1.putInt(“id”, 1);
    bundle2.putInt(“id”, 2);
    bundle3.putInt(“id”, 3);

    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab1”).setIndicator(“Tab 1”), (tabInfo = new TabInfo(“Tab1”, TabsFragment.class, bundle1)));
    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab2”).setIndicator(“Tab 2”), (tabInfo = new TabInfo(“Tab2”, TabsFragment.class, bundle2)));
    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab3”).setIndicator(“Tab 3”), (tabInfo = new TabInfo(“Tab3”, TabsFragment.class, bundle3)));

    I want a different contents of each tab. How do I dynamically set the content of each tab.
    Here my question at stackoverflow: http://stackoverflow.com/questions/10544602/set-webview-loadurl-programmatically-that-is-in-fragment-class

     
  34. newjay08

    May 11, 2012 at 05:08

    Hi, can you help me with this one? I only have one Fragment class instead of three. The problem is I can’t set programmatically the content of my fragment class. Here’s my changes from your code.

    ***TabsViewPagerFragmentActivity****

    Bundle bundle1 = new Bundle();
    Bundle bundle2 = new Bundle();
    Bundle bundle3 = new Bundle();
    bundle1.putInt(“id”, 1);
    bundle2.putInt(“id”, 2);
    bundle3.putInt(“id”, 3);

    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab1”).setIndicator(“Tab 1”), (tabInfo = new TabInfo(“Tab1”, TabsFragment.class, bundle1)));
    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab2”).setIndicator(“Tab 2”), (tabInfo = new TabInfo(“Tab2”, TabsFragment.class, bundle2)));
    FragmentTabsPagerActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab3”).setIndicator(“Tab 3”), (tabInfo = new TabInfo(“Tab3”, TabsFragment.class, bundle3)));

    I want a different contents of each tab. How do I dynamically set the content of each tab.
    Here my question at stackoverflow: http://stackoverflow.com/questions/10544602/set-webview-loadurl-programmatically-that-is-in-fragment-class

     
  35. Ryan

    June 20, 2012 at 16:32

    Great tutorial!!! 1 problem is when having a ListView on a fragment. The ListView intercepts the touch events and I can no longer swipe left and right (probably because the ListView blocks the swipes and is trying to use the touch events for itself). Any solution to this?????

     
    • mitchwongho

      June 21, 2012 at 00:26

      Odd. ListView would catch vertical swipes while paging would handle horizontal swipes. Are you using a ListView Fragment?

       
  36. shahzadrocks

    July 5, 2012 at 08:08

    Reblogged this on AndroidForAll and commented:
    Slide Tabs With ViewPager

     
  37. shahzadrocks

    July 5, 2012 at 08:11

    Nice one…I downloaded the zip file but its showing error….though i have included compatibilty library ….+1 to u Reblogged it

     
  38. Renato Canha Ambrosio

    July 7, 2012 at 19:08

    Hello,

    Your code is exactly what I was looking for. I copy all .java and .xml code to Eclipse. No erros but does not worked. Probably I need to modify the AndroidManifest to declare the Activities. I thing PagerAdapter and TabsViewPagerFragmentActivity are not Activities to declate on AndroidManifest, right?
    Could you help me with some tips to solve this problem?
    I am not a programming, I am a Chemistry professor.

     
  39. Eddie

    July 8, 2012 at 21:20

    Love this tutorial. I’d like to see a fourth continuation in the series. Where and how do we insert elements/data/actions/lists etc? In the above example, the body is blank — except for the color defined in the layout. I’d love to see where do put the “meat” of the content in relation to the above. Buttons, Lists, AsyncTasks, etc…

     
  40. Mal Clarke

    July 10, 2012 at 16:07

    ROTATE PROBLEM FIX

    I had headaches over this one. But managed to fix it.

    Add to each of your TabXFragment.java classes

    @Override
    public void onSaveInstanceState(Bundle outState) {

    outState.putString(“tab”, “Tab1”); //save the tab selected
    super.onSaveInstanceState(outState);

    }

    changing the Tab1 for TabX. Solved it for me.

    Happy coding 🙂

     
  41. Renato Canha Ambrosio

    July 13, 2012 at 14:17

    Hello
    I included several buttons on xml fragments. I would like to know how to adapt the java code in these fragments to suport buttons.

     
  42. Ivan

    July 15, 2012 at 11:08

    Great article!
    Is it possible to move actionBar to bottom?

     
  43. Oattoreto

    July 30, 2012 at 04:22

    Hi
    First , Thanks for Tutor, useful
    But i have a question ..

    Can i set CurrentTab ?
    and how?

    thk alot

     
  44. Abhinov

    August 10, 2012 at 11:56

    Hello

    I am completely new to android and even i am not good in programming i liked ur tutorial a lot its really nice i have a small doudt u said to add the Android Compatibility library i didnt get u where do we need to add the compatibility file so we import it and add that file going into properties and add libraries.and when we give the .apk file to the user we will not give the compatability file right then how will it run.should we keep both the files in different packages in the same project what should i do exactly plz “mitchwongho” help me and i dont find any supporting libraries at android developers to download plz rly me fast…

    Thanks A lot In Advance

     
  45. ismarslomic

    August 15, 2012 at 22:04

    Hi! Great blog!

    I have re-used most of your code in my app, but I’m experiencing very strange behavior. One of my fragments is a LisftFragment which is initiated and added to the list of fragments at intialiseViewPager() as in your example. The ListFragment is setting the ListAdapter at its onActivityCreated() method.

    Now, here comes the strange behaviour. When I debug the application and I hold the mobile vertically one ListFragment is created and the ListAdapter is set at onActivityCreated method correctly. When I rotate the mobile horizontally two ListFragments are created, but the onActivityCreated() is called only once (for only one of the ListFragment instances).

    The first instance of ListFragment is calling the onActivityCreated() and setting the ListAdapter. It seems like the super.onCreate(savedInstanceState) in FragmentActivity.onCreate(Bundle savedInstanceState) method is creating this instance (WHY??). This ListFragment is not added to the mPagerAdapter.

    The second instance of ListFragment is created from intialiseViewPager() as in your tutorial, it is also added to the mPagerAdapter but the onActivityCreated() is never called and therefor ListAdapter is also empty.

    Now, the second strange thing is that I can still see all the data in ListView horizontally as vertically mode.

    So I could just ignore this issue since the user doesn’t see it, but the thing is that I want to get the ListAdapter of current fragment (tab) in FragmentActivity and line 4 below will be null when i switch to horizontal mode.

    1. int pos = this.mTabHost.getCurrentTab();
    2. PagerAdapter pa = (PagerAdapter)this.mViewPager.getAdapter();
    3. MyListFragment f = (MyListFragment)pa.getItem(pos);
    4. ListAdapter la = f.getListAdapter()

    I’m very confused and I have spent lot of time debugging this. I understand if my explanation is very bad and that you might need some clarifications. Just let me know!

    Thanks for your time!

    Ismar

     
  46. willem

    August 23, 2012 at 22:50

    Hi,
    Great tutorial.
    Do you know the best way to remove the “padding” above the text?
    I have tried to set padding to 0dp in the xml in various places, but that doesn’t seem to work.
    I dislike to big empty space on top of the text, makes it eat more space than required.
    Thanks.

     
  47. David Greenfield (@energyAlchemist)

    August 31, 2012 at 10:33

    Awesome post, thanks

     
  48. Magnus

    October 1, 2012 at 16:01

    Hi
    Awesome Tutorial and everything was really helpful, I’ve got one problem though.
    My FragmentActivity-extended class (ActivityMain) is having some issues regarding it’s superclass.
    Logcat:

    10-01 15:48:58.695: D/dalvikvm(28280): Late-enabling CheckJNI
    10-01 15:48:58.780: W/dalvikvm(28280): Unable to resolve superclass of Lcom/plingnote/ActivityMain; (20)
    10-01 15:48:58.780: W/dalvikvm(28280): Link of class ‘Lcom/plingnote/ActivityMain;’ failed
    10-01 15:48:58.780: D/AndroidRuntime(28280): Shutting down VM
    10-01 15:48:58.780: W/dalvikvm(28280): threadid=1: thread exiting with uncaught exception (group=0x40c5d1f8)
    10-01 15:48:58.790: E/AndroidRuntime(28280): FATAL EXCEPTION: main
    10-01 15:48:58.790: E/AndroidRuntime(28280): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.plingnote/com.plingnote.ActivityMain}: java.lang.ClassNotFoundException: com.plingnote.ActivityMain
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1894)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread.access$600(ActivityThread.java:128)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.os.Handler.dispatchMessage(Handler.java:99)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.os.Looper.loop(Looper.java:137)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread.main(ActivityThread.java:4517)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at java.lang.reflect.Method.invokeNative(Native Method)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at java.lang.reflect.Method.invoke(Method.java:511)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at dalvik.system.NativeStart.main(Native Method)
    10-01 15:48:58.790: E/AndroidRuntime(28280): Caused by: java.lang.ClassNotFoundException: com.plingnote.ActivityMain
    10-01 15:48:58.790: E/AndroidRuntime(28280): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.Instrumentation.newActivity(Instrumentation.java:1027)
    10-01 15:48:58.790: E/AndroidRuntime(28280): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1885)
    10-01 15:48:58.790: E/AndroidRuntime(28280): … 11 more

    Any help is appreciated :)!

     
  49. amit

    October 13, 2012 at 11:30

    ERROR/AndroidRuntime(1264): Caused by: java.lang.ClassCastException:
    help me

    import java.util.HashMap;

    import java.util.List;

    import java.util.Vector;

    import android.content.Context;

    import android.os.Bundle;

    import android.support.v4.app.Fragment;

    import android.support.v4.app.FragmentActivity;

    import android.support.v4.view.ViewPager;

    import android.view.View;

    import android.widget.TabHost;

    import android.widget.TabHost.TabContentFactory;

    /**

    * The TabsViewPagerFragmentActivity class implements the Fragment activity that maintains a TabHost using a ViewPager.

    * @author mwho

    */

    public class TabsViewPagerFragmentActivity extends FragmentActivity implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {

    private TabHost mTabHost;

    private ViewPager mViewPager;

    private HashMap mapTabInfo = new HashMap();

    private PagerAdapter mPagerAdapter;

    /**

    *

    * @author mwho

    * Maintains extrinsic info of a tab’s construct

    */

    private class TabInfo {

    private String tag;

    private Class clss;

    private Bundle args;

    private Fragment fragment;

    TabInfo(String tag, Class clazz, Bundle args) {

    this.tag = tag;

    this.clss = clazz;
    this.args = args;

    }

    }

    /**

    * A simple factory that returns dummy views to the Tabhost

    * @author mwho

    */

    class TabFactory implements TabContentFactory {

    private final Context mContext;

    /**

    * @param context

    */

    public TabFactory(Context context) {

    mContext = context;

    }

    /** (non-Javadoc)
    * @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)

    */

    public View createTabContent(String tag) {
    View v = new View(mContext);

    v.setMinimumWidth(0);
    v.setMinimumHeight(0);
    return v;

    }

    }

    /** (non-Javadoc)

    * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)

    */

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // Inflate the layout

    setContentView(R.layout.tabs_viewpager_layout);

    // Initialise the TabHost

    this.initialiseTabHost(savedInstanceState);

    if (savedInstanceState != null) {

    mTabHost.setCurrentTabByTag(savedInstanceState.getString(“tab”)); //set the tab as per the saved state

    }

    // Intialise ViewPager

    this.intialiseViewPager();

    }

    /** (non-Javadoc)

    * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)

    */

    protected void onSaveInstanceState(Bundle outState) {

    outState.putString(“tab”, mTabHost.getCurrentTabTag()); //save the tab selected

    super.onSaveInstanceState(outState);

    }

    /**

    * Initialise ViewPager

    */

    private void intialiseViewPager() {

    List fragments = new Vector();

    fragments.add(Fragment.instantiate(this, Next.class.getName()));

    fragments.add(Fragment.instantiate(this, Latest.class.getName()));

    fragments.add(Fragment.instantiate(this, Metrics.class.getName()));

    this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);

    //

    this.mViewPager = (ViewPager)super.findViewById(R.id.viewpager);

    this.mViewPager.setAdapter(this.mPagerAdapter);

    this.mViewPager.setOnPageChangeListener(this);

    }
    // ERROR/AndroidRuntime(1066): Caused by: java.lang.ClassCastException

    /**

    * Initialise the Tab Host

    */

    private void initialiseTabHost(Bundle args) {

    mTabHost = (TabHost)findViewById(android.R.id.tabhost);

    mTabHost.setup();

    TabInfo tabInfo = null;

    TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab1”).setIndicator(“Tab 1”), ( tabInfo = new TabInfo(“Tab1”, Next.class, args)));

    this.mapTabInfo.put(tabInfo.tag, tabInfo);

    TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab2”).setIndicator(“Tab 2”), ( tabInfo = new TabInfo(“Tab2”, Latest.class, args)));

    this.mapTabInfo.put(tabInfo.tag, tabInfo);

    TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec(“Tab3”).setIndicator(“Tab 3”), ( tabInfo = new TabInfo(“Tab3”, Metrics.class, args)));

    this.mapTabInfo.put(tabInfo.tag, tabInfo);

    // Default to first tab

    //this.onTabChanged(“Tab1”);

    //

    mTabHost.setOnTabChangedListener(this);

    }

    /**

    * Add Tab content to the Tabhost

    * @param activity

    * @param tabHost

    * @param tabSpec

    * @param clss

    * @param args

    */

    private static void AddTab(TabsViewPagerFragmentActivity activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {

    // Attach a Tab view factory to the spec

    tabSpec.setContent(activity.new TabFactory(activity));

    tabHost.addTab(tabSpec);

    }

    /** (non-Javadoc)
    * @see android.widget.TabHost.OnTabChangeListener#onTabChanged(java.lang.String)

    */

    public void onTabChanged(String tag) {

    //TabInfo newTab = this.mapTabInfo.get(tag);

    int pos = this.mTabHost.getCurrentTab();

    this.mViewPager.setCurrentItem(pos);

    }

    /* (non-Javadoc)

    * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)

    */

    @Override

    public void onPageScrolled(int position, float positionOffset,

    int positionOffsetPixels) {

    // TODO Auto-generated method stub

    }

    /* (non-Javadoc)

    * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageSelected(int)

    */

    @Override

    public void onPageSelected(int position) {

    // TODO Auto-generated method stub

    this.mTabHost.setCurrentTab(position);

    }

    /* (non-Javadoc)

    * @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)

    */

    @Override

    public void onPageScrollStateChanged(int state) {

    // TODO Auto-generated method stub

    }

    }

     
  50. Adit Lal

    October 17, 2012 at 21:21

    I get the following error in logcat , pls help

    FATAL EXCEPTION: main
    10-18 00:44:33.649: E/AndroidRuntime(4524): java.lang.NullPointerException
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:352)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:347)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.app.FragmentPagerAdapter.instantiateItem(FragmentPagerAdapter.java:99)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:692)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.view.ViewPager.populate(ViewPager.java:821)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.view.ViewPager.populate(ViewPager.java:772)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1234)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4816)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4816)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4816)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.measureVertical(LinearLayout.java:833)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4816)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.View.measure(View.java:15172)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1850)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1102)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1275)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4214)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.Choreographer.doCallbacks(Choreographer.java:555)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.Choreographer.doFrame(Choreographer.java:525)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.os.Handler.handleCallback(Handler.java:615)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.os.Handler.dispatchMessage(Handler.java:92)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.os.Looper.loop(Looper.java:137)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at android.app.ActivityThread.main(ActivityThread.java:4931)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at java.lang.reflect.Method.invokeNative(Native Method)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at java.lang.reflect.Method.invoke(Method.java:511)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
    10-18 00:44:33.649: E/AndroidRuntime(4524): at dalvik.system.NativeStart.main(Native Method)

     
  51. polo

    November 11, 2012 at 16:59

    A Great Big Thanks 🙂

     
  52. intika

    November 30, 2012 at 09:44

    Hi gays, gooooood news to all 🙂

    Screen Orientation Bug Is Solved !!!!!!!!!

    and the solution is too too stupid ! here is the stuff,just add

    android:configChanges=”orientation|keyboardHidden|screenSize”

    in manifest xml under activity ! that’s all loooool

    ———————————————————————————
    Adapt depending on the version of your android os
    ———————————————————————————
    Full Code : for Android 3.2 (API level 13) and newer:
    ——————————————————————

    ———————————————————————————
    Older version use :
    ————————
    android:configChanges=”keyboardHidden|orientation”
    ———————————————————————————
    I just used this code to test, i found an 100x easier way to add the swipe to a tabhost 🙂
    nor ActionBarSherlock nor ViewPageIndicator … too much stuff on that library and it’s ruining my code….

    The stuff is just to use a ViewPager with the tabwidget, setup the viewpager, and then replace the the tab framelayout with the viewpager or equivalent…
    ———————————————————————————
    good luck to all it’s really not easy to manage cosmetic under java android… i’am new on it and it’s really too bad stuff you quickly loose many days just to get a f****** stuff displayed as you want… in an other hand it’s cool to get all that support and documentation…
    ———————————————————————————
    cheeeeeeeeerrrrrrrrrsssssssssssss

     
  53. intika

    November 30, 2012 at 09:46

     
  54. intika

    November 30, 2012 at 09:47

    full code wont be displayed… just add
    ———————————————————————————————————-
    android:name=”IndexActivity”
    android:theme=”@android:style/Theme.Light”
    android:configChanges=”orientation|keyboardHidden|screenSize”
    ———————————————————————————————————-
    and
    ———————————————————————————————————-
    android:name=”.fragments.tabs.TabsViewPagerFragmentActivity”
    android:configChanges=”orientation|keyboardHidden|screenSize”
    ———————————————————————————————————-
    Cheers

     
  55. intika

    November 30, 2012 at 09:50

    one last post … lol
    explanation : when screen orientation change the activity is reseted… when the reset happen if active tab is not the first one the variables get ruined… so just disable that reset… 😉

     
  56. intika

    November 30, 2012 at 09:55

    i think “Oattoreto” is still looking for setting active tab still july hahahahaha loool

    mTabHost.setCurrentTabByTag(“Tab2”);

     
  57. Amrit

    December 7, 2012 at 18:55

    Hi I have followed the steps and managed to create 3 slide tabs but how can I edit the 3 tabs with content and text and other programmes for it to function?

    Any help will be great

    thanks

     
  58. joonazzz

    December 28, 2012 at 15:46

    Thanks a lot for sharing this. I needed tabs + swipe on android 2.2 and it works great! You saved a lot of time for me !

     
  59. Hassan

    January 11, 2013 at 15:01

    Hi,
    Looking to be a nice tutorial.I haven’t implemented yet but I want to implement horizantal pager slider like u Have done plus want to add portion of next and previous pages as implemented in “groupme” app.Any idea or help is appreciated.Thanks

     
  60. rajni

    January 16, 2013 at 10:54

    hii,,tnx for giving nice post and now i wnn to creat an app which have a home page look a like this image so may u like to help me by some example,,, the image link is http://imgur.com/pJjFk

     
  61. DoLpHiN

    January 29, 2013 at 22:09

    Hi, thx for great tutorial.
    Could you tell me how to modify tabs appearance? I’m new to Android development and i don’t get it.

     
  62. Athira

    January 31, 2013 at 08:21

    Hi,
    Thank you…
    very helpful for my project..:)

     
  63. Ahsan

    February 8, 2013 at 21:51

    Hi its a usefull tutorial kindly tell me how to render a activity on each tab ?? plus at tab2 i need 2 sub tabs.. ??

     
  64. Chip

    February 11, 2013 at 03:31

    People might still be complaining about the rotation issue so I thought to add this workaround.

    In the main activity, I drop the NULL handler for the savedInstance, and just use the initializeViewPager() method directly. I also add savedInstanceState methods to the fragments and this solves it. Hope that helps other folks thought the build is on a Nexus 4, v4.2.

     
  65. Deep

    February 28, 2013 at 10:56

    hiiii,

    I want a listview with custom rows in these pagers how can we do that??

    Please help me . I am new in android.

     
  66. Prakash

    March 1, 2013 at 22:16

    Hi mitchwongho
    not sure you are still here. I followed your tutorial and have run into some problem. Just wondering whether you can help me.

    Prakash

     
  67. click_whir

    April 5, 2013 at 00:19

    Why are you managing a list of fragments? I thought ViewPager was supposed to manage all that for you….

     
  68. Antoni

    April 5, 2013 at 01:05

    Thanks a lot, great tutorial, has been very useful to me, ….but a simple question:
    is there an easy way to control de color and size of tab text labels ???

     
    • Antoni

      April 7, 2013 at 13:36

      solved it !
      replacing the view widget at every TabWidget int onTabChanged method by these sentences:
      mTabHost.getTabWidget().removeViewAt(tabPosition);
      mTabHost.getTabWidget().addView(button, tabPosition);
      where button is the new predefined View for the TabWidget, with its own color, icon, ….

       
  69. Ruben

    April 18, 2013 at 02:16

    Hi, I have an error in this line:

    fragments.add(Fragment.instantiate(this, Home.class.getName()));

    The error in LogCat:

    04-18 02:10:58.601: E/AndroidRuntime(31519): FATAL EXCEPTION: main
    04-18 02:10:58.601: E/AndroidRuntime(31519): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.lesson_planner/com.example.lesson_planner.MainActivity}: java.lang.ClassCastException: com.example.lesson_planner.Home cannot be cast to android.support.v4.app.Fragment

    Anybody can help me?

     
    • mitchwongho

      April 20, 2013 at 10:37

      Have you included the compatibility library? Are you extending the correct Fragment class (android.support.v4.app.Fragment)

       
  70. Giovanni

    April 23, 2013 at 15:17

    Hi,
    Thanks for the useful article. I’ve got a question about 2 lines of code:
    1) tabSpec.setContent(activity.new TabFactory(activity));, specially the part inside the brackets
    2) List fragments = new Vector();, I know it’s pure java, but I can’t figure it out anyway. How can I do this in another way? Possibly more simple.

    Thanks a lot.. I’m beginning to learn Android from a few days.
    Bye.

     
  71. Andres Añez

    May 23, 2013 at 00:58

    Hi
    Well i tried to folow the code with an app doing exactly the same but when i make it run it stops, here´s all i got with LogCat, hope u can help me, thanks

    05-22 18:23:11.821: D/dalvikvm(581): Not late-enabling CheckJNI (already on)
    05-22 18:23:14.531: D/AndroidRuntime(581): Shutting down VM
    05-22 18:23:14.531: W/dalvikvm(581): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
    05-22 18:23:14.571: E/AndroidRuntime(581): FATAL EXCEPTION: main
    05-22 18:23:14.571: E/AndroidRuntime(581): java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.LinearLayout
    05-22 18:23:14.571: E/AndroidRuntime(581): at com.tabsviewpager.Tab1Fragment.onCreateView(Tab1Fragment.java:26)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.Fragment.performCreateView(Fragment.java:1460)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:911)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.view.ViewPager.populate(ViewPager.java:1064)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.view.ViewPager.populate(ViewPager.java:911)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1432)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.measureVertical(LinearLayout.java:812)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1369)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.measureVertical(LinearLayout.java:660)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.measureVertical(LinearLayout.java:812)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.LinearLayout.onMeasure(LinearLayout.java:553)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4677)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
    05-22 18:23:14.571: E/AndroidRuntime(581): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2072)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.View.measure(View.java:12603)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1044)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2418)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.os.Handler.dispatchMessage(Handler.java:99)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.os.Looper.loop(Looper.java:137)
    05-22 18:23:14.571: E/AndroidRuntime(581): at android.app.ActivityThread.main(ActivityThread.java:4340)
    05-22 18:23:14.571: E/AndroidRuntime(581): at java.lang.reflect.Method.invokeNative(Native Method)
    05-22 18:23:14.571: E/AndroidRuntime(581): at java.lang.reflect.Method.invoke(Method.java:511)
    05-22 18:23:14.571: E/AndroidRuntime(581): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    05-22 18:23:14.571: E/AndroidRuntime(581): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    05-22 18:23:14.571: E/AndroidRuntime(581): at dalvik.system.NativeStart.main(Native Method)
    05-22 18:23:23.042: I/Process(581): Sending signal. PID: 581 SIG: 9

     
  72. Alexandre

    June 27, 2013 at 15:47

    Thank you. Really great set of postings.

     
  73. Mambo

    July 2, 2013 at 03:00

    Hi mitchwongho
    Great your tutorial!
    I have a problem with an idea that I have,,, but i dont know if this is possible..
    i tell you:
    i wanna make a app that has this application:
    http://developer.android.com/training/implementing-navigation/nav-drawer.html
    and the selectItem(int position) method call a Fragment class that have the TabHost…
    Something like:
    1. The Navigation drawer is same
    2. Pressing an one option of Navigation drawer menu .. this show a Fragment with a TabHost with various Tabs…

    Is this possible?
    Thx for advance!

     
  74. Mohammad

    July 22, 2013 at 13:52

    Hello,
    thank you very mush for this great tutorial.
    I have a annoying problem. I follow all of the steps but after running it my first tab is empty. I’m sure the problem isn’t about layout.
    I post a question in stackoverflow too:http://stackoverflow.com/questions/17786445/first-page-of-viewpager-is-not-loading-at-all
    help me plz

     
  75. neelam

    August 13, 2013 at 11:24

    hi
    i want to develope an app like skout.not all the features but few of them like swipe on click on image buttons on header.pls see this link as i want to make it
    like https://play.google.com/store/apps/details?id=com.skout.android&hl=en

     
  76. Himanshu

    September 26, 2013 at 14:42

    hey can you write the OnTabChanged Method for this code.So that the Fragments are not created every time.It should just load

     
  77. Vinicios

    October 11, 2013 at 15:53

    Men i hava five fragments, if the name is very long, the name break the line, i need what the TabWidget follow fragment

     
    • Vinicios

      October 11, 2013 at 15:54

      don’t break line in tab

       
      • Mal Clarke

        October 23, 2013 at 09:42

        Hold the line
        Love isn’t always on time

         
  78. Innkuan Thute

    November 19, 2013 at 16:13

    I would like to apply custom design on TabHost. How can I design?

     
  79. Enrique

    November 22, 2013 at 23:56

    Good tutorial. I tried to download the code from Github, but I have no access.

     
  80. BB

    November 26, 2013 at 16:36

    thank you . Its a good code.

     
  81. Lê Đình Thanh Hải

    December 2, 2013 at 05:44

    good! it helpful for me! thank you so much! 🙂

     
  82. gabby

    January 24, 2014 at 09:20

    HOW CAN I ADD ACTIVE SVG IMAGES ON THE SWIPING TAB

     
  83. Omar Espinoza

    January 27, 2014 at 22:42

    I read your tutorial, I have an application that has a FragmenActivity (menu), open a fragment and this uses the Tab + ViewPager, works great.

    I press the back button and enter again the fragment (Tab + ViewPager), the information does not appear in the tabs.

    What am I doing wrong.

     
  84. Wilb

    March 3, 2014 at 07:14

    How do this with ActionBarCopat? … with FragMent Activity the Action Bar is not compatible with all devices.

     
  85. eugeniusz

    March 22, 2014 at 13:55

    Great example, thank you!

     
  86. uttami

    April 7, 2014 at 11:44

    how can i align tabs at the other sides of the page?? or can i give desired position to these tabs??

     
  87. Hari Krishna G

    August 13, 2014 at 12:39

    Can we get the same code for Tabs at the screen below

     
  88. Supost Java Cdcn

    October 9, 2014 at 04:04

    Hello !Thank you! I learned a lot from your article.
    If I want to show vertical tabs, then how can I do?

     
  89. Kareem

    February 9, 2015 at 19:36

    Thank you very much for this tutorial!!

     
  90. shriduttkothari

    February 13, 2015 at 19:30

    Thanks awesome work mate..

     

Leave a reply to Sohayb Cancel reply