Is there a way to add margin between the tabs in a TabLayout? I've tried with using a custom style for Widget.Design.TabLayout, but there are properties only related to padding, but no margins.
-
1margin means what.. gaps between the tabs? – Connecting life with Android Apr 11 '16 at 12:39
-
Seems adding margins is not really possible however you can do some tricks to make it work. may b add a dummy view or tabs. – Connecting life with Android Apr 11 '16 at 12:44
7 Answers
Ok mates, after spending 2-3 hours on that I finally found a solution.
If you are using TabLayout there is no way to add margins to the tabs by using styles and so on. (as @Connecting life with Android earlier)
But, you can do that by writing some Java code. All in all your code should look similar to that one:
for(int i=0; i < mTabLayout.getTabCount(); i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}
In order to get each and every tab as a View we have to first get the container which contains them. In this case the TabLayout is using a SlidingTabStrip as a container for the tabs. The SlidingTabStrip is the first child of the TabLayout:
View tab = ((ViewGroup) mTabLayout.getChildAt(0))
And after this small detail, everything is pretty straight forward.

- 1,789
- 1
- 13
- 20
-
2Your solution works really well for me! If someone wants to add a margin contained in the dimens.xml file, he can use getResources().getDimensionPixelSize(R.dimen.your_dimens) instead of a fixed pixel value like "50". – Mattia Ruggiero Nov 23 '16 at 10:59
-
1This works, however the underline indicator begins to misbehave when you do this, swiping works fine, but paging to a given point on tab click breaks it. I'm looking into a fix now. – JMRboosties Dec 27 '16 at 03:13
-
-
-
@Todor Your answer is good. The code snippet you shared does not set margin for last tab. So Can you tell me how can i achieve this ? – Deepak Rathore Apr 12 '19 at 07:25
-
@DeepakRathore the above implementation sets margin to the last tab. – Todor Kostov Apr 12 '19 at 07:36
Here's how I did it in pure xml.
dimens.xml:
<!-- Set this to 50% of what you want the actual space between the tabs to be. -->
<dimen name="tab_spacing_half">5dp</dimen> <!-- i.e., 10dp spacing between tabs. -->
Layout containing your TabLayout:
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/tab_spacing_half"/>
Add this to your theme in styles.xml:
<item name="tabBackground">@drawable/tab_background</item>
drawable-nodpi\tab_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/tab_background_selected"
android:state_selected="true" />
<item
android:drawable="@drawable/tab_background_unselected"
android:state_selected="false"
android:state_focused="false"
android:state_pressed="false" />
</selector>
drawable-nodpi\tab_background_selected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thick"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>
...That's where the trick is. Effectively, wrapping your background shape in an item
with "padding" according to your @dimen/tab_spacing_half
value. And finally...
drawable-nodpi\tab_background_unselected.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="@dimen/tab_spacing_half"
android:right="@dimen/tab_spacing_half"
android:top="@dimen/tab_spacing_half"
android:bottom="@dimen/tab_spacing_half">
<shape
android:shape="rectangle">
<corners
android:radius="@dimen/border_radius_small">
</corners>
<stroke
android:width="@dimen/divider_height_thin"
android:color="@color/white">
</stroke>
</shape>
</item>
</layer-list>

- 18,324
- 27
- 171
- 253
-
-
This should be the accepted answer. No java/kotlin "hacking" needed for it to work. – Hampel Előd Mar 05 '20 at 08:06
-
That was a great answer and easily understandable. Thanks @ban-geoengineering – Sandy Nov 25 '20 at 09:30
Here is Kotlin version of @Todor Kostov's answer.
for (i in 0 until applicationList_tabLayout.tabCount) {
val tab = (applicationList_tabLayout.getChildAt(0) as ViewGroup).getChildAt(i)
val p = tab.layoutParams as ViewGroup.MarginLayoutParams
p.setMargins(10, 0, 10, 0)
tab.requestLayout()
}

- 197
- 2
- 3
-
-
@KishanSolanki It's working. The only thing is you need to place the code after setting the viewpager. Otherwise, there won't be any tabs set and the tab count will be 0. You need to give applicationList_tabLayout.tabCount - 1 also. – Anju Jun 10 '22 at 07:06
@Todor Kostov answered well, but the center of the tabs are slipped away because the last tab has margin too.
so use mTabLayout.getTabCount() - 1
instead of just mTabLayout.getCodeCount()
.
for(int i=0; i < mTabLayout.getTabCount() - 1; i++) {
View tab = ((ViewGroup) mTabLayout.getChildAt(0)).getChildAt(i);
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) tab.getLayoutParams();
p.setMargins(0, 0, 50, 0);
tab.requestLayout();
}

- 1,227
- 11
- 22
None of the answers was working for me! So here is the answer that will work for you and see the below result.

- 13,761
- 4
- 85
- 82
This is how set margin for four different tabs. You can change the setMargins(v1,v2,v3,v4)
function values to get a suitable fitting for the number of tabs that you are working with. I hope this helps. Please note that tabHost
is the object of TabHost
hosting different tabs you are working with.
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
View currentView;
for(int i=0; i<tabHost.getTabWidget().getChildCount(); i++) {
//This code removes divider between tabs
tabHost.getTabWidget().setDividerDrawable(null);
tabHost.getTabWidget().getChildAt(i).setLayoutParams(new
LinearLayout.LayoutParams((width / 8) - 2, 50));
currentView = tabHost.getTabWidget().getChildAt(i);
LinearLayout.LayoutParams currentLayout =
(LinearLayout.LayoutParams) currentView.getLayoutParams();
currentLayout.setMargins(30, 5, 80, 0);
}

- 5,981
- 17
- 77
- 128

- 515
- 6
- 14
Most suggestions here seems to suggest calling requestLayout() to update the margins. This will trigger a new layout pass. I also personally saw issues when animating the layout, in which the TabLayout was defined, causing the requestLayout to be called a bunch of times, and sometimes making the tabs "jump"
I think a better way of setting the margins between the tabs, would be to extend the TabLayout, and listen to when child views are added to the SlidingTabIndicator.
private const val YOUR_CUSTOM_MARGIN = 8
class CustomTabLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : TabLayout(
context,
attrs,
defStyleAttr
) {
init {
val tabStrip = (this.getChildAt(0) as ViewGroup)
tabStrip.setOnHierarchyChangeListener(object : OnHierarchyChangeListener {
override fun onChildViewAdded(p0: View?, p1: View?) {
if (p1 is TabView && p1.layoutParams is MarginLayoutParams) {
val params = p1.layoutParams as MarginLayoutParams
params.setMargins(YOUR_CUSTOM_MARGIN, 0, YOUR_CUSTOM_MARGIN, 0)
}
}
override fun onChildViewRemoved(p0: View?, p1: View?) {}
})
}
}

- 131
- 5