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.
Whereas style.xml will contain:
In your FragmentActivity's onCreate(), add the following code.
Implement the IconPagerAdapter for showing icons and background in both normal and selected states. In this sample we will support 4 pages.
Now its time to modify the library project's TabPageIndicator.java like this.
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); }