Shripad Bhat
Shripad Bhat

Reputation: 2443

How to align active tab center in android Sliding Tab Layout

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

Upvotes: 8

Views: 13870

Answers (3)

Lubos Horacek
Lubos Horacek

Reputation: 1582

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

Upvotes: 2

Shripad Bhat
Shripad Bhat

Reputation: 2443

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

Upvotes: 3

Yuri Heupa
Yuri Heupa

Reputation: 1238

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

Upvotes: 13

Related Questions