Saturday, May 17, 2014

Pager Tabs with Icon and text which appears to have fixed width.

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.


PagerTab
 
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);
}

No comments:

Post a Comment

Android aar deployment in Maven - 2022

Introduction If you are working on android library project, you might be wondering how to publish it on Maven like this . Earl...