TabLayout no rellena el ancho cuando tabMode se establece en 'scrollable'

He agregado TabLayout (desde la biblioteca de soporte v22.2.1) a mi Fragmento como:

 <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"/> 

El problema es que cuando la orientación del fragmento es horizontal (antes o después de la creación inicial del fragmento), TabLayout no coincide con el ancho del Fragment (sí, el padre tiene su ancho definido como match_parent también).

Cuando el ancho de la pantalla es pequeño (es decir, no todas las pestañas se pueden mostrar al mismo tiempo): Introduzca aquí la descripción de la imagen

Cuando el ancho de la pantalla es lo suficientemente grande como para mostrar todas las fichas (vea el espacio en blanco a la derecha): Introduzca aquí la descripción de la imagen

Si cambio tabMode a fixed, el ancho se llena pero las pestañas son demasiado pequeñas. ¿Hay alguna solución adecuada por ahí?

Supongo que esta es la manera más sencilla de lograr lo que quieres.

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

En lugar de crear TabLayout personalizado y hackear o crear más disposiciones que actúa como envoltorio alrededor de TabLayout sólo para el fondo. Prueba esto,

 <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"/> 

Esto establecerá el fondo detrás de tabLayout en lugar de establecer el fondo detrás de cada ficha.

Prueba con estos cambios

  <android.support.design.widget.TabLayout android:id="@+id/sliding_tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed" app:tabGravity="fill" /> 

Utilice por favor esto solucionará definitivamente este problema

 <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMaxWidth="0dp" app:tabGravity="fill" app:tabMode="fixed" /> 

Por favor, compruebe esto creo que funciona

Public class MainActivity extends AppCompatActivity {

 private TextView mTxv_Home, mTxv_News, mTxv_Announcement; private View mView_Home, mView_News, mView_Announcements; private HorizontalScrollView hsv; private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTxv_Home = (TextView) findViewById(R.id.txv_home); mTxv_News = (TextView) findViewById(R.id.txv_news); mTxv_Announcement = (TextView) findViewById(R.id.txv_announcements); mView_Home = (View) findViewById(R.id.view_home); mView_News = (View) findViewById(R.id.view_news); mView_Announcements = (View) findViewById(R.id.view_announcements); hsv = (HorizontalScrollView) findViewById(R.id.hsv); viewPager = (ViewPager) findViewById(R.id.viewpager); setupViewPager(viewPager); DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); int wt = displaymetrics.widthPixels/3; mTxv_Home.setWidth(wt); mTxv_News.setWidth(wt); // mTxv_Announcement.setWidth(wt); mTxv_Home.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mTxv_Home.setTextColor(Color.parseColor("#3F51B5")); mTxv_News.setTextColor(Color.parseColor("#808080")); mTxv_Announcement.setTextColor(Color.parseColor("#808080")); mView_Home.setBackgroundColor(Color.parseColor("#3F51B5")); mView_News.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8")); hsv.post(new Runnable() { public void run() { hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT); } }); viewPager.setCurrentItem(0); } }); mTxv_News.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mTxv_Home.setTextColor(Color.parseColor("#808080")); mTxv_News.setTextColor(Color.parseColor("#3F51B5")); mTxv_Announcement.setTextColor(Color.parseColor("#808080")); mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_News.setBackgroundColor(Color.parseColor("#3F51B5")); mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8")); hsv.post(new Runnable() { public void run() { int centerX = hsv.getChildAt(0).getWidth()/2; hsv.scrollTo(centerX, 0); } }); viewPager.setCurrentItem(1); } }); mTxv_Announcement.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mTxv_Home.setTextColor(Color.parseColor("#808080")); mTxv_News.setTextColor(Color.parseColor("#808080")); mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5")); mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_News.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5")); hsv.post(new Runnable() { public void run() { hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }); viewPager.setCurrentItem(2); } }); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (position == 0) { mTxv_Home.setTextColor(Color.parseColor("#3F51B5")); mTxv_News.setTextColor(Color.parseColor("#808080")); mTxv_Announcement.setTextColor(Color.parseColor("#808080")); mView_Home.setBackgroundColor(Color.parseColor("#3F51B5")); mView_News.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8")); hsv.post(new Runnable() { public void run() { hsv.fullScroll(HorizontalScrollView.FOCUS_LEFT); } }); } else if (position == 1) { mTxv_Home.setTextColor(Color.parseColor("#808080")); mTxv_News.setTextColor(Color.parseColor("#3F51B5")); mTxv_Announcement.setTextColor(Color.parseColor("#808080")); mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_News.setBackgroundColor(Color.parseColor("#3F51B5")); mView_Announcements.setBackgroundColor(Color.parseColor("#E8E8E8")); hsv.post(new Runnable() { public void run() { int centerX = hsv.getChildAt(0).getWidth()/2; hsv.scrollTo(centerX, 0); } }); } else if (position == 2) { mTxv_Home.setTextColor(Color.parseColor("#808080")); mTxv_News.setTextColor(Color.parseColor("#808080")); mTxv_Announcement.setTextColor(Color.parseColor("#3F51B5")); mView_Home.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_News.setBackgroundColor(Color.parseColor("#E8E8E8")); mView_Announcements.setBackgroundColor(Color.parseColor("#3F51B5")); hsv.post(new Runnable() { public void run() { hsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }); } } @Override public void onPageScrollStateChanged(int state) { } }); } private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFragment(new HomeFragment(), "Home"); adapter.addFragment(new NewsFragment(), "News"); adapter.addFragment(new AnnouncementsFragment(), "Announcements"); viewPager.setAdapter(adapter); } class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); public ViewPagerAdapter(FragmentManager manager) { super(manager); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } public void addFragment(Fragment fragment, String title) { mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public CharSequence getPageTitle(int position) { return mFragmentTitleList.get(position); } } 

}

 <HorizontalScrollView android:id="@+id/hsv" android:layout_width="fill_parent" android:layout_height="56dp" android:layout_weight="0" android:fillViewport="true" android:measureAllChildren="false" android:scrollbars="none" > <LinearLayout android:id="@+id/innerLay" android:layout_width="fill_parent" android:layout_height="50dp" android:orientation="horizontal" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/txv_home" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="Home" android:singleLine="true" android:paddingLeft="35dp" android:paddingRight="35dp" android:gravity="center" android:textSize="15sp"/> <View android:id="@+id/view_home" android:layout_width="match_parent" android:layout_height="3dp" android:background="@color/colorPrimary" /> </LinearLayout> <View android:layout_width="1dp" android:layout_height="match_parent" android:visibility="gone" android:background="#e8e8e8"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/txv_news" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="News" android:singleLine="true" android:paddingLeft="35dp" android:paddingRight="35dp" android:gravity="center" android:textSize="15sp"/> <View android:id="@+id/view_news" android:layout_width="match_parent" android:layout_height="3dp" android:background="#e8e8e8"/> </LinearLayout> <View android:layout_width="1dp" android:layout_height="match_parent" android:visibility="gone" android:background="#e8e8e8"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/txv_announcements" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:singleLine="true" android:text="Announcements" android:paddingLeft="35dp" android:paddingRight="35dp" android:gravity="center" android:textSize="15sp"/> <View android:id="@+id/view_announcements" android:layout_width="match_parent" android:layout_height="1dp" android:background="#e8e8e8"/> </LinearLayout> </LinearLayout> </HorizontalScrollView> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/hsv" /> 

No me importaba que las pestañas llenaran el ancho, pero me importaba que el color de fondo no se expandiera a todo el ancho. Así que pensé en esta solución, donde pongo un FrameLayout detrás con el mismo color de fondo que las pestañas.

 <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/MyColor"> <android.support.design.widget.TabLayout android:id="@+id/tabs" style="@style/MyCustomTabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable"/> </FrameLayout> 

@ Dtx12 respuesta no funciona si cualquier título de pestaña es mayor que (measuredWidth / tabCount).

Hay mi subclase TabLayout para esta situación (en Kotlin). Espero que esto ayude a alguien.

 class FullWidthTabLayout : 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 onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { super.onLayout(changed, l, t, r, b) if (changed) { val widths = mutableListOf<Int>() for (i in 0..this.tabCount - 1) { widths.add(this.getTabAt(i)!!.customView!!.width) } if (widths.sum() < this.measuredWidth) { var equalPart: Long = this.measuredWidth.toLong() / this.tabCount.toLong() var biggerWidths = widths.filter { it > equalPart } var smallerWidths = widths.filter { it <= equalPart } var rest: Long = this.measuredWidth.toLong() - biggerWidths.sum() while (biggerWidths.size != 0) { equalPart = rest / smallerWidths.size biggerWidths = smallerWidths.filter { it >= equalPart } smallerWidths = smallerWidths.filter { it < equalPart } rest -= biggerWidths.sum() } val minWidth = (rest / smallerWidths.size) + 10 //dont know why there is small gap on the end, thats why +10 for (i in 0..this.tabCount - 1) { this.getTabAt(i)!!.customView!!.minimumWidth = minWidth.toInt() } } } } } 
  • Cómo hacer la alineación del título de la pestaña a la izquierda en TabLayout en Android
  • Diferencia entre PagerTabStrip y TabLayout
  • No se encontró ninguna vista para id 0x7f0e00d5 (com.example.page:id/dialogViewpager) para el fragmento OneFragment {92c0220 # 1 id = 0x7f0e00d5 android: switcher: 2131624149: 0}
  • Android ViewPager Cargando fragmentos incorrectos
  • ¿Cómo puedo cambiar el color de fondo de una pestaña cuando se usa TabLayout?
  • Android CoordinatorLayout - Inconsistencias entre versiones de Android
  • Navegación anterior separada para un buscador de vistas con pestañas en Android
  • Cómo configurar el tamaño del icono en TabLayout?
  • Cambiar el relleno de TextView en TabLayout
  • Fragmento en TabLayout sólo carga cuando el usuario desliza Android
  • TabLayout eliminar desplazamiento innecesario
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.