android center align the selected tab in tablayout
Asked Answered
S

4

14

I am using android support design tablayout. Here's my code:

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content""
        app:tabGravity="center"
        app:tabMode="scrollable"
        />

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

My issue is the tabs always align left. However, I would like to center the selected tab (even at the beginning, the first(selected) tab should be centered). Is there a way to do this? Thanks.

Sievert answered 18/8, 2015 at 22:29 Comment(4)
Have you found an answer for this?Stagecoach
If you get the answer, please update usRoden
Have you got any solution to this?Kursh
app:tabMode="scrollable" change to app:tabMode="fixed". if you set scrollable then assumed that there are many tabs so it will start from left side.Owlish
D
24

I took a look into TabLayout and tabContentStart only sets padding for its first child -> SlidingTabStrip, so I set it manually on 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);
    }
}

TabLayout's first 0 index child is the SlidingTabStrip.

Demonism answered 27/4, 2016 at 9:53 Comment(7)
This keeps calling requestLayout() in an infinite loop.Chilopod
After switching fragments tabs shifts left.Compatible
Supper Solution, ThanksLoculus
is it working? , for me requestlayout is in infinite loopBlessing
This makes my tabs spinning infinite as well.Pachston
I don't know how to support RTL with this solutionPerez
java.lang.NullPointerException: (getChildAt(0) as ViewGroup).getChildAt(0) must not be nullJarid
S
5

Perhaps you are looking for an xml attribute called app:tabContentStart. This attribute allows you push the active tab to the left according to the value specified, which is set in "dp" (kind of like a margin-left thing). For example, try putting your code like this:

    <android.support.design.widget.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="scrollable"
        app:tabContentStart="96dp"/> <-- Or whatever value you want here.

It doesn't exactly center the tab, but it gives you a similar effect as the Google Play Store tabs.

Sweeps answered 6/11, 2015 at 8:47 Comment(1)
Perfect answer, that's exactly what I was searching for hours.Tavey
S
5
public class MyTabLayout extends TabLayout {

    public MyTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        setTabMode(MODE_SCROLLABLE);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (!changed) return;
        int totalTabsWidth = 0;
        for (int i = 0; i < getTabCount(); i++)
            totalTabsWidth += ((ViewGroup) getChildAt(0)).getChildAt(i).getWidth();
        int padding = (getWidth() - totalTabsWidth) / 2;
        if (padding < 0) padding = 0;
        getChildAt(0).setPaddingRelative(padding, 0, padding, 0);
    }
}
Shirty answered 28/1, 2018 at 3:8 Comment(0)
N
2

If your target API is 23 or above, let me share one more option for consideration along with the configuration of app:tabContentStart suggested by SynerFlow, which could let the end Tab be centered instead of swiped to the left-most edge during scrolling. However, I am still figuring out the approach for API before 23.

final int TAB_CONTENT_START = 96;   

tabLayout.setOnScrollChangeListener(new View.OnScrollChangeListener() {

    @Override
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

        final int maxAllowWidthOfTabBar = tabLayout.getMeasuredWidth() + TAB_CONTENT_START;
        if (scrollX > maxAllowWidthOfTabBar)
            tabLayout.setScrollX(maxAllowWidthOfTabBar);

    }
});
Nathanielnathanil answered 19/1, 2017 at 8:29 Comment(1)
This should be the default answer so to save my time from trying out all the failing suggestions.Despoil

© 2022 - 2024 — McMap. All rights reserved.