8
votes

I have 12 items in android sliding tab layout + view pager. While sliding from left to right, selected tab should be center same as play store. Please help me how to do that. In my application active tab is always left of the screen.

enter image description here

enter image description here

3
Are you using PagerTabStrip in your project (that is what Google Play app is using). Looks like you are using normal tabs instead.Marko
No, I have used SlidingTabLayout class which is provided by google as a sample class for sliding tab layout. Also i have tried PagerTabStrip it doesn't allow you to slide tab title like play store. SlidingTabLayout is extended HorizontalScrollView.Shripad Bhat
I see. Looking at this video from Android developers, you can see this is not the expected behavior. In order to get the effect that Google Play has, you have to use PagerTabStrip. It is super easy to implement, checkout this tutorial.Marko
Thanks Mark. I got the issue resolved below is my answer.Shripad Bhat
The SmartTabLayout does this very nicely.M. Reza Nasirloo

3 Answers

13
votes

My approach differs a bit of the Shripad Bhat solution, which bounce the tab at the end of the slide.

Here's my workaround...

Changes to onPageScrolled method:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    int tabStripChildCount = mTabStrip.getChildCount();
    if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
        return;
    }

    mTabStrip.onViewPagerPageChanged(position, positionOffset);

    View selectedTitle = mTabStrip.getChildAt(position);
    int selectedOffset = (selectedTitle == null) ? 0 : selectedTitle.getWidth();
    int nextTitlePosition = position + 1;
    View nextTitle = mTabStrip.getChildAt(nextTitlePosition);
    int nextOffset = (nextTitle == null) ? 0 : nextTitle.getWidth();
    int extraOffset = (int)(0.5F * (positionOffset * (float)(selectedOffset + nextOffset)));
    scrollToTab(position, extraOffset);

    if (mViewPagerPageChangeListener != null) {
        mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
    }
}

Changes to scrollToTab method:

private int mLastScrollTo;

private void scrollToTab(int tabIndex, int positionOffset) {
    final int tabStripChildCount = mTabStrip.getChildCount();
    if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
        return;
    }

    View selectedChild = mTabStrip.getChildAt(tabIndex);
    if (selectedChild != null && selectedChild.getMeasuredWidth() != 0) {

        int targetScrollX = ((positionOffset + selectedChild.getLeft()) - getWidth() / 2) + selectedChild.getWidth() / 2;

        if (targetScrollX != mLastScrollTo) {
            scrollTo(targetScrollX, 0);
            mLastScrollTo = targetScrollX;
        }
    }
}
3
votes

Google Has provided sample for sliding tab layout. But in the implementation of SlidingTabLayout class, it was not designed for center align the selected tab. I have modify the scroll method to make the selected/active tab center of the screen. Here is the code change:

Class Name: SlidingTabLayout

Line Number: 241, scrollToTab{}

Updated Method:

private void scrollToTab(int tabIndex, int positionOffset) {
    final int tabStripChildCount = mTabStrip.getChildCount();
    if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
        return;
    }

    View selectedChild = mTabStrip.getChildAt(tabIndex);
    if (selectedChild != null) {
        int targetScrollX = selectedChild.getLeft() + positionOffset;

        if (tabIndex > 0 || positionOffset > 0) {
            // If we're not at the first child and are mid-scroll, make sure we obey the offset
            targetScrollX -= (getWidth()-selectedChild.getWidth())/2;
        }

        scrollTo(targetScrollX, 0);
    }
}
2
votes

Had this problem as well. tabLayout provides only tabContentStart option, needed both sides:

public class CenteringTabLayout extends TabLayout {
public CenteringTabLayout(Context context) {
    super(context);
}

public CenteringTabLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CenteringTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    View firstTab = ((ViewGroup)getChildAt(0)).getChildAt(0);
    View lastTab = ((ViewGroup)getChildAt(0)).getChildAt(((ViewGroup)getChildAt(0)).getChildCount()-1);
    ViewCompat.setPaddingRelative(getChildAt(0), (getWidth()/2) - (firstTab.getWidth()/2),0,(getWidth()/2) - (lastTab.getWidth()/2),0);
}
}