Friday, June 22, 2012

ViewPager

android.support.v4.view.ViewPager is Layout manager that allows the user to flip left and right through pages of data.

Note this class is currently under early design and development. The API will likely change in later updates of the compatibility library, requiring changes to the source code of apps when they are compiled against the newer version.

ViewPager


(This example implement ViewPager using FragmentPagerAdapter. For ViewPager using custom PagerAdapter, read HERE.)

To use compatibility library, Android Support Package is needed. Refer to last post to "Add Android Support Package".

Create three Fragments, each one corresponding to one tab. Please note that the Fragment(s) extends android.support.v4.app.Fragment. 

MyFragmentA.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragmentA extends Fragment {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_a, container, false);
  return myFragmentView;
 }

}


/res/layout/fragment_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment A" />
   <ImageView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:src="@drawable/ic_launcher"/>
</LinearLayout>


MyFragmentB.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragmentB extends Fragment {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_b, container, false);
  return myFragmentView;
 }

}


/res/layout/fragment_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment B" />
   <ImageView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:scaleType="center"
       android:src="@drawable/ic_launcher"/>
</LinearLayout>


MyFragmentC.java
package com.exercise.AndroidViewPager;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragmentC extends Fragment {

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {
  View myFragmentView = inflater.inflate(R.layout.fragment_c, container, false);
  return myFragmentView;
 }

}


/res/layout/fragment_c.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >
   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="It's Fragment C" />

</LinearLayout>


Main code, AndroidViewPagerActivity.java
package com.exercise.AndroidViewPager;

import java.util.ArrayList;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class AndroidViewPagerActivity extends FragmentActivity {
 
 ViewPager mViewPager;
 TabsAdapter mTabsAdapter;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mViewPager = new ViewPager(this);
        mViewPager.setId(R.id.pager);
        setContentView(mViewPager);
        
        final ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
        
        mTabsAdapter = new TabsAdapter(this, mViewPager);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment A"),
                MyFragmentA.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment B"),
          MyFragmentB.class, null);
        mTabsAdapter.addTab(bar.newTab().setText("Fragment C"),
          MyFragmentC.class, null);

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }

    }

 @Override
 protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
 }
 
 public static class TabsAdapter extends FragmentPagerAdapter
  implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
  
  private final Context mContext;
        private final ActionBar mActionBar;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
        
        static final class TabInfo {
            private final Class<?> clss;
            private final Bundle args;

            TabInfo(Class<?> _class, Bundle _args) {
                clss = _class;
                args = _args;
            }
        }

  public TabsAdapter(FragmentActivity activity, ViewPager pager) {
   super(activity.getSupportFragmentManager());
            mContext = activity;
            mActionBar = activity.getActionBar();
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }

  public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
            TabInfo info = new TabInfo(clss, args);
            tab.setTag(info);
            tab.setTabListener(this);
            mTabs.add(info);
            mActionBar.addTab(tab);
            notifyDataSetChanged();
        }

  @Override
  public void onPageScrollStateChanged(int state) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onPageSelected(int position) {
   // TODO Auto-generated method stub
   mActionBar.setSelectedNavigationItem(position);
  }

  @Override
  public void onTabReselected(Tab tab, FragmentTransaction ft) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public void onTabSelected(Tab tab, FragmentTransaction ft) {
   Object tag = tab.getTag();
            for (int i=0; i<mTabs.size(); i++) {
                if (mTabs.get(i) == tag) {
                    mViewPager.setCurrentItem(i);
                }
            }
  }

  @Override
  public void onTabUnselected(Tab tab, FragmentTransaction ft) {
   // TODO Auto-generated method stub
   
  }

  @Override
  public Fragment getItem(int position) {
   TabInfo info = mTabs.get(position);
            return Fragment.instantiate(mContext, info.clss.getName(), info.args);
  }

  @Override
  public int getCount() {
   return mTabs.size();
  }

 }

}


Download the files.

!!! It's a bug here: when change orientation, NullPointerException will be thrown. Please refer to next post "NullPointerException of ViewPager when change orientation" for my solution.

Next:
- Communication between Fragments in ViewPager
ViewPager example, with switching page programmatically

Related:
- ActionBar in Tab navigation mode

3 comments:

Zen said...

Zen said...

Awesome, thanks just exactly was i was looking for :D just remove the FragmentActivity for SherlockFragmentActivity for full support older devices :D thanks a lot

Anonymous said...

Nothing explained i dont see the interest