We are going to create pager tabs, which unlike default library will be able to show more than 3 tabs in a screen. All the tabs will close to each other.
To achieve this purpose we shall need a library located at
http://viewpagerindicator.com/. Download the library project, named as JakeWharton-Android-ViewPagerIndicator-2.4.1-0-g8cd549f.zip. It includes a library and sample project. We need library for our app. If you are curious, you may check the sample project as well. Import the library project in eclipse.
Create a new Android project and open its properties. Add library project in this project using Android section in properties. Clean library and android project. Add the following in your activity_layout.xml.
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/indicator"
style="@style/CustomTabPageIndicator"
android:layout_width="fill_parent"
android:layout_height="30dp"
android:visibility="gone"/>
<android.support.v4.view.ViewPager
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:context=".VMEBaseClass" >
</android.support.v4.view.ViewPager>
Whereas style.xml will contain:
<style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
<!-- <item name="android:background">@drawable/custom_tab_indicator</item> -->
<item name="android:textAppearance">@style/CustomTabPageIndicator.Text</item>
<item name="android:textColor">#cccccc</item>
<item name="android:textSize">12sp</item>
<!-- <item name="android:divider">@drawable/vertical_line</item> -->
<!-- @drawable/custom_tab_indicator_divider</item> -->
<!-- <item name="android:dividerPadding">10dp</item>
<item name="android:showDividers">middle</item> -->
<item name="android:paddingLeft">0dp</item>
<item name="android:paddingRight">0dp</item>
<item name="android:fadingEdge">horizontal</item>
<item name="android:paddingTop">1dp</item>
<item name="android:paddingBottom">0dp</item>
<item name="android:fadingEdgeLength">8dp</item>
<item name="android:layout_marginTop">5dp</item>
<item name="android:layout_marginBottom">5dp</item>
</style>
In your FragmentActivity's onCreate(), add the following code.
BasePagerAdapter mSectionsPagerAdapter = new BasePagerAdapter( getSupportFragmentManager( ) );
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById( R.id.pager );
mViewPager.setAdapter( mSectionsPagerAdapter );
TabPageIndicator indicator = (TabPageIndicator) findViewById( R.id.indicator );
indicator.setVisibility( View.VISIBLE );
indicator.setViewPager( mViewPager );
Implement the IconPagerAdapter for showing icons and background in both normal and selected states. In this sample we will support 4 pages.
public class BasePagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
public VMEBasePagerAdapter( FragmentManager fm ) {
super( fm );
}
@Override
public Fragment getItem( int position ) {
// getItem is called to instantiate the fragment for the given page.
if ( position == 0 ) {
Fragment fragment = new DownloadFragment();
return fragment;
} else if ( position == 1 ) {
Fragment fragment = new FavoriteFragment( favoriteData);
return fragment;
} else if ( position == 2 ) {
Fragment fragment = new FlashFragment();
return fragment;
} else if ( position == 3 ) {
Fragment fragment = null;
fragment = new DummyFragment();
return fragment;
} else {
return null;
}
}
@Override
public int getCount( ) {
//Return the count of pages.
return 4;
}
@Override
public CharSequence getPageTitle( int position ) {
switch ( position ) {
case 0:
return getString( R.string.title_download );
case 1:
return getString( R.string.title_favorite );
case 2:
return getString( R.string.title_flash );
case 3:
return getString( R.string.title_dummy );
}
return null;
}
@Override
public int getIconResIdNormal( int index ) {
switch ( index ) {
case 0:
return R.drawable.ic_normal_download;
case 1:
return R.drawable.ic_normal_favorite;
case 2:
return R.drawable.ic_normal_flash;
case 3:
return R.drawable.ic_normal_dummy;
}
return 0;
}
@Override
public int getIconResIdSelected( int index ) {
switch ( index ) {
case 0:
return R.drawable.ic_selected_download;
case 1:
return R.drawable.ic_selected_favorite;
case 2:
return R.drawable.ic_selected_flash;
case 3:
return R.drawable.ic_selected_dummy;
}
return 0;
}
@Override
public int getBackgroundResIdSelected( int index ) {
switch ( index ) {
case 0:
return R.drawable.tab_left_pressed;
case 1:
case 2:
return R.drawable.tab_center_pressed;
case 3:
return R.drawable.tab_right_pressed;
}
return 0;
}
@Override
public int getBackgroundResIdNormal( int index ) {
switch ( index ) {
case 0:
return R.drawable.tab_left_normal;
case 1:
case 2:
return R.drawable.tab_center_normal;
case 3:
return R.drawable.tab_right_normal;
}
return 0;
}
}
Now its time to modify the library project's TabPageIndicator.java like this.
public class TabPageIndicator extends HorizontalScrollView implements PageIndicator {
/** Title text used when no title is provided by the adapter. */
private static final CharSequence EMPTY_TITLE = "";
//private Vector< TabView > tabViews = new Vector< TabPageIndicator.TabView >( );
/**
* Interface for a callback when the selected tab has been reselected.
*/
public interface OnTabReselectedListener {
/**
* Callback when the selected tab has been reselected.
*
* @param position
* Position of the current center item.
*/
void onTabReselected( int position );
}
private Runnable mTabSelector;
private final OnClickListener mTabClickListener = new OnClickListener( ) {
public void onClick( View view ) {
//TabView tabView = (TabView) view;
final int oldSelected = mViewPager.getCurrentItem( );
final int newSelected = (Integer)view.getTag( );
mViewPager.setCurrentItem( newSelected );
if ( oldSelected == newSelected && mTabReselectedListener != null ) {
mTabReselectedListener.onTabReselected( newSelected );
}
}
};
private final IcsLinearLayout mTabLayout;
private ViewPager mViewPager;
private ViewPager.OnPageChangeListener mListener;
private int mMaxTabWidth;
private int mSelectedTabIndex;
private OnTabReselectedListener mTabReselectedListener;
public TabPageIndicator( Context context ) {
this( context, null );
}
public TabPageIndicator( Context context, AttributeSet attrs ) {
super( context, attrs );
setHorizontalScrollBarEnabled( false );
mTabLayout = new IcsLinearLayout( context, R.attr.vpiTabPageIndicatorStyle );
addView( mTabLayout, new ViewGroup.LayoutParams( WRAP_CONTENT, MATCH_PARENT ) );
}
public void setOnTabReselectedListener( OnTabReselectedListener listener ) {
mTabReselectedListener = listener;
}
@Override
public void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) {
final int widthMode = MeasureSpec.getMode( widthMeasureSpec );
final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
setFillViewport( lockedExpanded );
final int childCount = mTabLayout.getChildCount( );
if ( childCount > 1 && ( widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST ) ) {
if ( childCount > 2 ) {
mMaxTabWidth = (int) ( MeasureSpec.getSize( widthMeasureSpec ) * 0.4f );
} else {
mMaxTabWidth = MeasureSpec.getSize( widthMeasureSpec ) / 2;
}
} else {
mMaxTabWidth = -1;
}
final int oldWidth = getMeasuredWidth( );
super.onMeasure( widthMeasureSpec, heightMeasureSpec );
final int newWidth = getMeasuredWidth( );
if ( lockedExpanded && oldWidth != newWidth ) {
// Recenter the tab display if we're at a new (scrollable) size.
setCurrentItem( mSelectedTabIndex );
}
}
private void animateToTab( final int position ) {
final View tabView = mTabLayout.getChildAt( position );
if ( mTabSelector != null ) {
removeCallbacks( mTabSelector );
}
mTabSelector = new Runnable( ) {
public void run( ) {
final int scrollPos = tabView.getLeft( ) - ( getWidth( ) - tabView.getWidth( ) ) / 2;
smoothScrollTo( scrollPos, 0 );
mTabSelector = null;
}
};
post( mTabSelector );
}
@Override
public void onAttachedToWindow( ) {
super.onAttachedToWindow( );
if ( mTabSelector != null ) {
// Re-post the selector we saved
post( mTabSelector );
}
}
@Override
public void onDetachedFromWindow( ) {
super.onDetachedFromWindow( );
if ( mTabSelector != null ) {
removeCallbacks( mTabSelector );
}
}
private void addTab( int index, CharSequence text, int iconResId ) {
LayoutInflater inflater = (LayoutInflater)getContext( ).getSystemService( Context.LAYOUT_INFLATER_SERVICE );
View view = inflater.inflate( R.layout.tab_layout, null);
ImageView imageView = (ImageView)view.findViewById( R.id.ivIcon );
TextView textView = (TextView)view.findViewById( R.id.tvTabText );
imageView.setImageResource( iconResId );
textView.setText( text );
view.setOnClickListener( mTabClickListener );
view.setTag( index );
mTabLayout.addView( view, new LinearLayout.LayoutParams( 0, MATCH_PARENT, 1 ) );
/*final TabView tabView = new TabView( getContext( ) );
tabView.mIndex = index;
tabView.setFocusable( true );
tabView.setOnClickListener( mTabClickListener );
tabView.setText( text );
if ( iconResId != 0 ) {
tabView.setCompoundDrawablesWithIntrinsicBounds( iconResId, 0, 0, 0 );
}
tabViews.add( tabView );
tabView.setCompoundDrawablePadding (-30 );
mTabLayout.addView( tabView, new LinearLayout.LayoutParams( 0, MATCH_PARENT, 1 ) );*/
}
/*public TabView getTabAt( int position ) {
if ( tabViews != null && tabViews.size( ) > position )
return tabViews.get( position );
return null;
}*/
@Override
public void onPageScrollStateChanged( int arg0 ) {
if ( mListener != null ) {
mListener.onPageScrollStateChanged( arg0 );
}
}
@Override
public void onPageScrolled( int arg0, float arg1, int arg2 ) {
if ( mListener != null ) {
mListener.onPageScrolled( arg0, arg1, arg2 );
}
}
@Override
public void onPageSelected( int arg0 ) {
setCurrentItem( arg0 );
if ( mListener != null ) {
mListener.onPageSelected( arg0 );
}
}
@Override
public void setViewPager( ViewPager view ) {
if ( mViewPager == view ) {
return;
}
if ( mViewPager != null ) {
mViewPager.setOnPageChangeListener( null );
}
final PagerAdapter adapter = view.getAdapter( );
if ( adapter == null ) {
throw new IllegalStateException( "ViewPager does not have adapter instance." );
}
mViewPager = view;
view.setOnPageChangeListener( this );
notifyDataSetChanged( );
}
public void notifyDataSetChanged( ) {
mTabLayout.removeAllViews( );
PagerAdapter adapter = mViewPager.getAdapter( );
IconPagerAdapter iconAdapter = null;
if ( adapter instanceof IconPagerAdapter ) {
iconAdapter = (IconPagerAdapter) adapter;
}
final int count = adapter.getCount( );
for ( int i = 0; i < count; i++ ) {
CharSequence title = adapter.getPageTitle( i );
if ( title == null ) {
title = EMPTY_TITLE;
}
int iconResId = 0;
if ( iconAdapter != null ) {
iconResId = iconAdapter.getIconResIdNormal( i );
}
addTab( i, title, iconResId );
}
if ( mSelectedTabIndex > count ) {
mSelectedTabIndex = count - 1;
}
setCurrentItem( mSelectedTabIndex );
requestLayout( );
}
@Override
public void setViewPager( ViewPager view, int initialPosition ) {
setViewPager( view );
setCurrentItem( initialPosition );
}
@Override
public void setCurrentItem( int item ) {
if ( mViewPager == null ) {
throw new IllegalStateException( "ViewPager has not been bound." );
}
mSelectedTabIndex = item;
mViewPager.setCurrentItem( item );
final int tabCount = mTabLayout.getChildCount( );
for ( int i = 0; i < tabCount; i++ ) {
final LinearLayout child = (LinearLayout) mTabLayout.getChildAt( i );
//final TabView child = (TabView) mTabLayout.getChildAt( i );
final boolean isSelected = ( i == item );
child.setSelected( isSelected );
PagerAdapter adapter = mViewPager.getAdapter( );
IconPagerAdapter iconAdapter = null;
if ( adapter instanceof IconPagerAdapter ) {
iconAdapter = (IconPagerAdapter) adapter;
}
int iconResId;
int bgResId;
if ( iconAdapter != null ) {
if ( isSelected ) {
iconResId = iconAdapter.getIconResIdSelected( i );
bgResId = iconAdapter.getBackgroundResIdSelected( i );
} else {
iconResId = iconAdapter.getIconResIdNormal( i );
bgResId = iconAdapter.getBackgroundResIdNormal( i );
}
if ( bgResId != 0 )
child.setBackgroundResource( bgResId );
ImageView iv = (ImageView)child.findViewById( R.id.ivIcon );
if ( iconResId != 0 ) {
iv.setVisibility( View.VISIBLE );
iv.setImageResource( iconResId );
}else{
iv.setVisibility( View.GONE );
}
}
if ( isSelected ) {
animateToTab( item );
}
}
}
@Override
public void setOnPageChangeListener( OnPageChangeListener listener ) {
mListener = listener;
}
}
Finally update library's IconPagerAdapter
.java
public interface IconPagerAdapter {
/**
* Get icon representing the page at {@code index} in the adapter.
*/
int getIconResIdNormal(int index);
/**
* Get icon representing the page at {@code index} in the adapter This will be used when the tab is selected.
*/
int getIconResIdSelected(int index);
// From PagerAdapter
int getCount();
/**
* Get background representing the page at {@code index} in the adapter This will be used when the tab is selected.
*/
int getBackgroundResIdSelected(int index);
/**
* Get background representing the page at {@code index} in the adapter..
*/
int getBackgroundResIdNormal(int index);
}