I have added TabLayout
(from support library v22.2.1) to my Fragment as:
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyColorAccentTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"/>
The issue is that when the Fragment's orientation is landscape (before or after the initial creation of the fragment), the TabLayout
doesn't match the width of the Fragment
(yes the parent has its width set to match_parent
as well).
When screen width is small (i.e not all tabs can be shown at same time):
When screen width is big enough to show all tabs (see the blank space at the right):
If I change tabMode
to fixed, width is filled but tabs are too small. Is there any proper solution out there?
App -> java -> packagename ->MainActivity.java Now, implement a method and create “TabLayout”, “ViewPager” and “Toolbar local variable”. Change theme. Now, set text or icon using addTab. Tabs are creating using “newTab() method”.
It is possible to use a TabLayout without a ViewPager by using a TabLayout. OnTabSelectedListener . For navigation within an Activity , manually populate the UI based on the tab selected.
Tab layout are visible below toolbar with View pager, used to create swipeable views . Tabs are designed to work with fragments. Use them to swipe fragments in view pager.
androidx version:
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"
/>
</androidx.viewpager.widget.ViewPager>
***** BELOW IS OLD ANSWER *****
Try this one, it's a workaround which sets tabMaxWidth="0dp"
, tabGravity="fill"
and tabMode="fixed"
.
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"/>
</android.support.v4.view.ViewPager>
Screenshot on a 10 inch tablet:
Instead of creating custom TabLayout and hacking around or creating more layouts which acts as wrapper around TabLayout only for background. Try this,
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
style="@style/MyColorAccentTabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<!-- Instead of setting app:tabBackground -->
android:background="@color/colorAccent"
app:tabGravity="fill"
app:tabMode="scrollable"/>
This will set background to behind tabLayout instead of setting background behind every tab.
I guess this is the simpliest way to achieve what you want.
public class CustomTabLayout extends TabLayout {
public CustomTabLayout(Context context) {
super(context);
}
public CustomTabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
try {
if (getTabCount() == 0)
return;
Field field = TabLayout.class.getDeclaredField("mTabMinWidth");
field.setAccessible(true);
field.set(this, (int) (getMeasuredWidth() / (float) getTabCount()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is my 2021 Kotlin solution. It achieves the following which I couldn't do from other answers:
To achieve this I created a subclass of TabLayout
that overrides onMeasure
class ScalableTabLayout : TabLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val tabLayout = getChildAt(0) as ViewGroup
val childCount = tabLayout.childCount
if (childCount > 0) {
val widthPixels = MeasureSpec.getSize(widthMeasureSpec)
val tabMinWidth = widthPixels / childCount
var remainderPixels = widthPixels % childCount
tabLayout.forEachChild {
if (remainderPixels > 0) {
it.minimumWidth = tabMinWidth + 1
remainderPixels--
} else {
it.minimumWidth = tabMinWidth
}
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
And then used it in my layout file:
<com.package.name.ScalableTabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabMode="scrollable" />
both tabMaxWidth="0dp"
and tabMode="scrollable"
are required
please use this it will solve this problem definitely
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed" />
I have tried almost all answeres, atlast found this one works like a charm.
public void dynamicSetTabLayoutMode(TabLayout tabLayout) {
int tabWidth = calculateTabWidth(tabLayout);
int screenWidth = getApplicationContext().getResources().getDisplayMetrics().widthPixels;
if (tabWidth <= screenWidth) {
tabLayout.setTabMode(TabLayout.MODE_FIXED);
} else {
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
}
}
private int calculateTabWidth(TabLayout tabLayout) {
int tabWidth = 0;
for (int i = 0; i < tabLayout.getChildCount(); i++) {
final View view = tabLayout.getChildAt(i);
view.measure(0, 0);
tabWidth += view.getMeasuredWidth();
}
return tabWidth;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With