77

I am using the new android.support.design.widget.TabLayout of v7-appcompat library, and found a problem, there is no way to set the divider between the tabs, dont know if there is.

I have successfully configured the pager adapter and the tabs are looking good but cant set the divider between the tabs.

I want this type of tabs

Tab1 | Tab2 | Tab3

but currently its showing

Tab1  Tab2  Tab3

My xml is

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >

        <include layout="@layout/toolbar" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/shape_tabbar_background"
            app:tabIndicatorColor="@android:color/white"
            app:tabIndicatorHeight="4dp" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

I am adding tabs by this

viewPager = (ViewPager) findViewById(R.id.viewpager);
    viewPager.setOffscreenPageLimit(2);
    adapter = new TabAdapterLoginActivity(getSupportFragmentManager(),
            titles);
    viewPager.setAdapter(adapter);
    tabLayout = (TabLayout) findViewById(R.id.tablayout);
    tabLayout.setupWithViewPager(viewPager);
Gopal Singh Sirvi
  • 4,539
  • 5
  • 33
  • 55

8 Answers8

92

TabLayout is actually HorizontalScrollView and it's first child is LinearLayout.

So just use below code to add dividers

    View root = tabLayout.getChildAt(0);
    if (root instanceof LinearLayout) {
        ((LinearLayout) root).setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
        GradientDrawable drawable = new GradientDrawable();
        drawable.setColor(getResources().getColor(R.color.separator));
        drawable.setSize(2, 1);
        ((LinearLayout) root).setDividerPadding(10);
        ((LinearLayout) root).setDividerDrawable(drawable);
    }

Below is the sample screen shot

Screen 1 enter image description here

Screen 2 enter image description here

Jimit Patel
  • 4,265
  • 2
  • 34
  • 58
  • 2
    Nice solution ! thank you so much. For those who use an image as a divider, the image will be stretched out by the height of TabLayout, and there is a way to fix it: http://stackoverflow.com/questions/10706853/android-how-to-change-item-width-and-height – Phong Nguyen Apr 10 '17 at 06:44
  • 1
    should be the selected answer – Desolator Oct 08 '17 at 06:36
  • 1
    It is the simplest method. Thank you. – Cüneyt Nov 06 '17 at 08:52
  • 1
    This answer should be on top. – Andrain Feb 20 '18 at 12:12
  • 2
    It is working fine but it is showing divider before first tab which i can''t able to remove. – Narender Gusain Apr 01 '18 at 07:24
  • @NarenderGusain have you used the method `setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE)`? You can follow this link for more clarification https://developer.android.com/reference/android/widget/LinearLayout.html#SHOW_DIVIDER_MIDDLE – Jimit Patel Apr 02 '18 at 04:35
  • 5
    this solution is working but tabs have strange white space on left side after using this method – Zulqurnain Jutt Apr 14 '18 at 10:57
  • @ZulqurnainJutt I couldn't see any white space anywhere. I tried to use black background and white divider to make it visible. I have updated answer with screenshot. Please do let me know if there is particular thing you have added into it for the behavior you are facing. – Jimit Patel Apr 25 '18 at 06:54
  • I have posted my SO related to [this](https://stackoverflow.com/questions/49831234/divider-between-tabs-of-tablayout-programatically-linearlayout-show-divider-midd) – Zulqurnain Jutt Apr 25 '18 at 07:09
  • This solution DOES NOT WORK perfectly and shouldn't be used if you want a perfect UI. Even with the SHOW_DIVIDER_MIDDLE, the first tab will have a divider at the very beginning of it, not sure why. I would use the custom view method in the accepted answer instead. Plus it's not safe to grab children views for a view in the SDK that may change at any time, breaking the code used in this solution. – mpellegr May 01 '18 at 21:49
  • @mpellegr I'm not sure what you mean by doesn't work perfectly. I've posted with screenshots. And as far as breaking code is your opinion, if you do not want to use it's fine. I've seen lot of SDK bugs which I solve them by breaking their code – Jimit Patel May 02 '18 at 02:40
  • @JimitPatel I mean break the code as in if the SDK does not have a LinearLayout as child 0, this would code would crash your app.. But I see you have an instanceof check so it wouldn't crash, it just wouldn't do anything.. but! I am using this solution now, I am using a custom drawable though and for some reason the tab divider is not showing for the first item anymore! so maybe a custom drawable is needed instead of creating a GradientDrawable like this solution shows. – mpellegr May 02 '18 at 14:22
  • @ZulqurnainJutt see my above comments! I fixed this issue and I answered that question you posted. – mpellegr May 02 '18 at 16:16
  • @mpellegr If you say clean code, Google won't remove directly they will deprecate it and furthermore even if they remove it, existing live app won't be affected unless you change your version. And I hope you will test completely before releasing any app especially if change is regarding change in SDK version. To the point, I would ask what all config you use in gradle regarding android where Custom Drawable is working and GradientDrawable isn't. So this answer can be modified and can be useful for others. – Jimit Patel May 03 '18 at 05:13
  • @Jimit Patel this isn't dependent on what version of android you compiled with, it matters what the OS level of the phone itself. the version the user has may not have the child layout as needed for this solution to work. there's no guarantee that google won't change that so it's not safe to use it. it's different from using an API method which is going to always be supported on newer OS's, but using hacky methods to get certain views in a View class is not part of that guaranteed backwards compatibility, unless you have docs stating otherwise? – mpellegr Jun 11 '18 at 01:11
  • It works. I used `ColorDrawable` instead and would like to ask if there is a way to control the width of the divider? – Renat Kaitmazov Jul 16 '18 at 20:39
  • 1
    @RenatKaitmazov You will have to make custom drawable for that `LinearLayout`. You can follow this link for that https://stackoverflow.com/a/47680974/842607 – Jimit Patel Jul 17 '18 at 04:52
70

There is a way to add divider by using Tab setCustomView method:

TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);

for (int i = 0; i < tabLayout.getTabCount(); i++) {
      TabLayout.Tab tab = tabLayout.getTabAt(i);
      RelativeLayout relativeLayout = (RelativeLayout) 
            LayoutInflater.from(this).inflate(R.layout.tab_layout, tabLayout, false);

      TextView tabTextView = (TextView) relativeLayout.findViewById(R.id.tab_title);
      tabTextView.setText(tab.getText());
      tab.setCustomView(relativeLayout);
      tab.select();
}

Tab custom layout with divider (tab_layout.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<!-- Tab title -->
<TextView
    android:id="@+id/tab_title"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:textColor="@drawable/tab_item_selector"/>

<!-- Tab divider -->
<View
    android:layout_width="1dp"
    android:layout_height="match_parent"
    android:layout_alignParentLeft="true"
    android:background="@android:color/black" />
</RelativeLayout>

Set TabLayout tab horizontal padding to 0dp:

<android.support.design.widget.TabLayout
        android:id="@+id/tablayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shape_tabbar_background"
        app:tabIndicatorColor="@android:color/white"
        app:tabIndicatorHeight="4dp"

        app:tabPaddingStart="0dp"
        app:tabPaddingEnd="0dp" />

And a selector for tab title text color when it's selected (tab_item_selector.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:state_focused="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:state_pressed="true" android:color="@color/abc_primary_text_material_dark" />
    <item android:color="@color/abc_secondary_text_material_dark" />
</selector>
Aryan Najafi
  • 2,496
  • 27
  • 29
  • 1
    For some strange reason, for me it looks like `| Tab1 | Tab2 | Tab3` – Sekula1991 Dec 01 '15 at 00:11
  • It's because tab divider in layout is left aligned. You can change the property android:layout_alignParentLeft="true" to android:layout_alignParentRight="true". Additionally, if you wish to hide the divider on first tab, you can assign an id to it in tab_layout.xml, fetch it via findViewById() method in code and set its visibility to GONE (if i == 0 in the for loop). – Ivan Kušt Dec 01 '15 at 15:16
  • This works..but it select second tab. IF i change to first tab programatically,the text color looks unselected. – user3289108 Jan 22 '16 at 10:16
  • 1
    @user3289108 did you find any solution for get selected first tab? i never get selected and xml sector not working for first tab if i not click on any other tab. – RaRa May 13 '16 at 11:54
  • 1
    `for (int i = 1;...)` should remove divider from the first tab, and a `LinearLayout` in `Horizontal` _orientation_ should further simplify the layout. – Samuel Aug 03 '16 at 06:06
  • `tabSelect(position)` again triggers `setOnTabSelectedListener` and goes in loop – Akshay Oct 21 '16 at 11:40
  • @Aryan The divider is not showing properly in center. – Jimit Patel Nov 07 '16 at 11:30
1

I do not think it is possible though unless during Tab creation you specify a customView and add your divider so for instance; a TextView and you explicitly TextView.setCompoundDrawablesWithIntrinsicBounds(0, 0,(int)id_of_a_divider, 0);

like you try to detect if its the first Tab,

if(firstTab){
    tabLayout.getTabAt(0).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds(0, 0,(int)id_of_a_divider, 0);
    //some little casting
}else if(lastTab){
  //dont get any
   tabLayout.getTabAt(index).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds(0,0,0, 0);
 else{
    //the rest takes two sides,
     tabLayout.getTabAt(index).getCustomView()
    .setCompoundDrawablesWithIntrinsicBounds((int)id_of_a_divider
       , 0,(int)id_of_a_divider, 0);

i hope you, get my idea

Elltz
  • 10,730
  • 4
  • 31
  • 59
  • are you sure that there is no other way or any inbuilt functionality available? – Gopal Singh Sirvi Sep 01 '15 at 05:35
  • it is true only if there is no contradictory proof, lets wait till its disproved, but if you look at the TabLayout docs you do not see anything of that sort. so i am certain, till i'm not, but for now you could appreciate my effort though. :)@GopalSinghSirvi well for other ways you could use xml and styles, that's where my intel reaches. – Elltz Sep 03 '15 at 10:05
1

hi you can try this as workaround what i did as follow :-

1-create normal tablayout.

2-make the mode MODE_FIXED

2-adding it in framellayout and above it add linear layout horizonytal.

3-add buttons in horizontal layout as the number of your tabs and make the buttons equals in size layout_wight=1 for each button.

4-make the buttons background transparent.

3-add spertator between the buttons in horizinoal linearlayout layout via view or anyview and specify the widht as 0.5dp or what ever thick you want.

4-you can add yor clicks on buttons or change the button to any oter view that not handle the clicking so the tab under it will take the click action :).

it might be ugly solutuions but it works perfect and do the job

another hint if you want to change the background of the selected tab you can make the indicator hieght in tablayout style equale the actual height of the tablayout.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="vertical">


    <FrameLayout
        android:id="@+id/content_parent"

        android:layout_width="fill_parent"
        android:layout_height="fill_parent">


        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"

            android:background="@android:color/transparent" />




        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            style="@style/MyCustomTabLayout"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_gravity="bottom"
            android:background="#99888888"
            android:clickable="false"
            android:layoutDirection="rtl"

              />


        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="0.5dp"
            android:layout_gravity="bottom"
            android:layout_marginBottom="60dp"
            android:background="#60ffffff"></LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="60dp"
            android:layout_gravity="bottom|right"
            android:background="@android:color/transparent"
            android:orientation="horizontal">


            <Button
                android:id="@+id/button1"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true" />



            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button2"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button3"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button4"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

            <LinearLayout
                android:layout_width="0.5dp"
                android:layout_height="60dp"
                android:background="#60ffffff"></LinearLayout>

            <Button
                android:id="@+id/button5"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:clickable="true"

                />

        </LinearLayout>

    </FrameLayout>

and this is for style

 <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
        <item name="tabIndicatorColor">#50000000</item>
        <item name="tabTextAppearance">@style/MyCustomTabTextAppearance</item>
        <item name="tabIndicatorHeight">60dp</item>
        <item name="tabSelectedTextColor">#222222</item>
Ziad Gholmish
  • 861
  • 1
  • 9
  • 10
  • custom view would be a more elegant way to handle this, but like you said this does work. it might not be feasible though for some views to do this since you need to know the exact width of each tab, otherwise the divider won't be spaced out evenly. also this only works if the number of tabs is static and known before compile time. – mpellegr May 01 '18 at 21:53
1

Not Best but alternative way i used for current.

In Main.Xml

<android.support.design.widget.TabLayout
    android:id="@+id/tabs"
    style="@style/Base.Widget.Design.TabLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/master_color"
    app:elevation="0dp"
    app:tabMode="scrollable"
    app:tabPaddingEnd="2dp"
    app:tabPaddingStart="0dp"
    app:tabSelectedTextColor="@color/white"
    app:tabTextColor="#82c6e6" />

i am using fragment and do in onCreate() like

if (savedInstanceState == null) {
    replaceFragment(fragmentOne);
}

Set Tab

private void setupTabLayout() {

    fragmentOne = new FragmentOne();
    fragmentTwo = new FragmentTwo();

    allTabs.addTab(allTabs.newTab().setText("CURRENT YEAR"), true);
    allTabs.addTab(allTabs.newTab().setText("2015"));
    allTabs.addTab(allTabs.newTab().setText("2014"));
    allTabs.addTab(allTabs.newTab().setText("2013"));
    allTabs.addTab(allTabs.newTab().setText("2012"));
    allTabs.addTab(allTabs.newTab().setText("2011"));

    //Hide Indicator
    allTabs.setSelectedTabIndicatorColor(getResources().getColor(android.R.color.transparent));
    //Set Custom tab Background
    for (int i = 1; i < allTabs.getTabCount(); i++) {
        TabLayout.Tab tab = allTabs.getTabAt(i);
        RelativeLayout relativeLayout = (RelativeLayout)
                LayoutInflater.from(getActivity()).inflate(R.layout.tab_layout, allTabs, false);
        tvTabText = (TextView) relativeLayout.findViewById(R.id.tab_title);
        View view = (View) relativeLayout.findViewById(R.id.deviderView);

        tvTabText.setText(tab.getText());
        tab.setCustomView(relativeLayout);

        if (i == 0) {
            view.setVisibility(View.GONE);
            tab.select();
        }
    }

}

tab_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Tab title -->
    <TextView
        android:id="@+id/tab_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center_horizontal"
        android:padding="10dp"
        android:text="sdasd"
        android:textColor="@drawable/tab_item_selector"
        android:textSize="@dimen/text_size_normal"
        android:textStyle="bold" />

    <!-- Tab divider -->

    <View
        android:id="@+id/deviderView"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginBottom="15dp"
        android:layout_marginTop="15dp"
        android:background="@android:color/white"
        android:gravity="right" />

</RelativeLayout>

tab_item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:color="@android:color/white" />
    <item android:state_focused="true" android:color="@android:color/white" />
    <item android:state_pressed="true" android:color="@android:color/white" />
    <item android:color="#82c6e6" />
</selector>

Please consider as a optional answer always.

RaRa
  • 2,024
  • 1
  • 18
  • 29
0

try this, hope it works fine for you.

tab_activity.xml

<TabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </TabWidget>

            <View
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@color/edt_footer_bg" />

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="15dp"
                android:background="@android:color/transparent" >
            </FrameLayout>
        </LinearLayout>
    </TabHost>

home_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:mytextview="http://schemas.android.com/apk/res/com.bne"
    android:layout_height="50dp"
    android:layout_marginRight="2dp"
    android:background="@color/app_bg_inner"
    android:gravity="center"
    android:padding="10dp" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@drawable/tab_selector"
        android:textSize="@dimen/txt_12"
        mytextview:txt_custom_font="@string/RobotoRegular" />

</LinearLayout>
Parth Bhayani
  • 1,894
  • 3
  • 17
  • 35
-1

try to use this code to set divder in TabHost mTabHost.getTabWidget().setDividerDrawable(R.Color.blue);

Zeeshan Shabbir
  • 6,704
  • 4
  • 38
  • 74
Amey Bawiskar
  • 361
  • 1
  • 3
  • 17
-3

One way to add a custom divider is to set it programmatically:

tablayout.getTabWidget().setDividerDrawable(R.drawable.yourdivider image name);

Make sure however, you call this before you set the content of the tabs. It would crash on me if I called it after.

you can also use this line if this doesn't work

if(Build.VERSION.SDK_INT >= 11)
    tablayout.getTabWidget().setShowDividers(TabWidget.SHOW_DIVIDER_MIDDLE);
Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
mominapk
  • 81
  • 1
  • 12