studio resueltos para intuitivas herramientas ejercicios desarrollo curso con avanzado aplicaciones android android-layout android-tablayout

resueltos - Diseño de la pestaña de Android: ajuste el ancho del indicador de pestaña con respecto al título de la pestaña



herramientas de android studio pdf (10)

¿Hay alguna forma de ajustar el ancho del indicador de pestaña con respecto al título de la pestaña?


A partir de la biblioteca de soporte 28 puede hacer lo siguiente:

app:tabIndicatorFullWidth="false" app:tabPaddingStart="25dp" app:tabPaddingEnd="25dp"

Puede configurar el relleno deseado que afecta al indicador de pestaña.

También ahora puedes hacer esto:

app:tabIndicator="@drawable/tab_indicator"

esto establecerá un dibujo personalizable como indicador.

Ejemplo de dibujo personalizable:

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="@color/colorPrimary"/> <corners android:radius="5dp"/> </shape>


Ajustar el ancho del indicador de pestaña con respecto al título de la pestaña y agregar el relleno derecho con el título de la pestaña y el margen derecho con el indicador de pestaña.

public class TabLayoutActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tab_layout); TabLayout tabs = (TabLayout) findViewById(R.id.tabs); tabs.setTabTextColors(Color.parseColor("#727272"), Color.parseColor("#305b0d")); ViewPager pager = (ViewPager) findViewById(R.id.pager); TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager()); pager.setAdapter(adapter); tabs.setupWithViewPager(pager); wrapTabIndicatorToTitle(tabs,20,20); } public void wrapTabIndicatorToTitle(TabLayout tabLayout, int externalMargin, int internalMargin) { View tabStrip = tabLayout.getChildAt(0); if (tabStrip instanceof ViewGroup) { ViewGroup tabStripGroup = (ViewGroup) tabStrip; int childCount = ((ViewGroup) tabStrip).getChildCount(); for (int i = 0; i < childCount; i++) { View tabView = tabStripGroup.getChildAt(i); //set minimum width to 0 for instead for small texts, indicator is not wrapped as expected tabView.setMinimumWidth(0); // set padding to 0 for wrapping indicator as title tabView.setPadding(0, tabView.getPaddingTop(), 40, tabView.getPaddingBottom()); // setting custom margin between tabs if (tabView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) tabView.getLayoutParams(); if (i == 0) { // left setMargin(layoutParams, externalMargin, internalMargin); } else if (i == childCount - 1) { // right setMargin(layoutParams, internalMargin, externalMargin); } else { // internal setMargin(layoutParams, internalMargin, internalMargin); } } } tabLayout.requestLayout(); } } private void setMargin(ViewGroup.MarginLayoutParams layoutParams, int start, int end) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { layoutParams.setMarginStart(start); layoutParams.setMarginEnd(end); } else { layoutParams.leftMargin = start; layoutParams.rightMargin = end; } } }


Estoy seguro de la versión SDK necesaria, pero puede hacerlo directamente en su archivo XML, agregando el atributo de relleno usando el espacio de nombres de la aplicación.

Solo haz que tu TabLayout se vea así:

<android.support.design.widget.TabLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/tab" android:layout_width="match_parent" android:layout_height="wrap_content" ... app:tabPaddingEnd="0dp" app:tabPaddingStart="0dp" </android.support.design.widget.TabLayout>

Puedes mover los xmlns:app="http://schemas.android.com/apk/res-auto" para tu padre también, pero es tu elección :)

Gracias, leon por su respuesta, que me llevó a lograr eso mediante XML.


Hay un atributo llamado tabIndicatorFullWidth dentro de android.support.design.widget.TabLayout

<android.support.design.widget.TabLayout android:id="@+id/tablayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="@color/colorPrimary" app:tabIndicatorFullWidth="false" // tested okay on 8.1 , 6.0.1 app:tabTextColor="@color/colorAccent" app:tabTextAppearance="@style/CampusTabText" android:minHeight="?attr/actionBarSize" app:tabMaxWidth="0dp" app:tabGravity="fill" app:tabMode="fixed" />


Intenté 2 horas para varias soluciones, pero ninguna de ellas tiene un efecto perfecto.
El problema radica en el relleno del tabView, incluso si configuro su relleno en todo 0,
Las distintas pestañas tienen un relleno diferente y, por lo tanto, el tamaño del texto dentro de su TextView varía.

Entonces encontré esta biblioteca que la resolvió perfectamente.
https://github.com/H07000223/FlycoTabLayout
Como dijo @Stas Melnychenko, probablemente no podamos hacerlo a menos que reescribamos un TabLayout . Y esta biblioteca vuelve a escribir un TabLayout ...


La respuesta corta es "no". Aquí está la explicación.

Hay una clase privada SlidingTabStrip dentro de TabLayout que dibuja el indicador

@Override public void draw(Canvas canvas) { super.draw(canvas); // Thick colored underline below the current selection if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) { canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight, mIndicatorRight, getHeight(), mSelectedIndicatorPaint); } }

Creo que mIndicatorLeft y mIndicatorRight es lo que necesita. Estos campos se establecen en la misma clase:

private void setIndicatorPosition(int left, int right) { if (left != mIndicatorLeft || right != mIndicatorRight) { // If the indicator''s left/right has changed, invalidate mIndicatorLeft = left; mIndicatorRight = right; ViewCompat.postInvalidateOnAnimation(this); } }

donde los parámetros izquierdo y derecho se calculan en el siguiente método:

private void updateIndicatorPosition() { final View selectedTitle = getChildAt(mSelectedPosition); int left, right; if (selectedTitle != null && selectedTitle.getWidth() > 0) { left = selectedTitle.getLeft(); right = selectedTitle.getRight(); if (mSelectionOffset > 0f && mSelectedPosition < getChildCount() - 1) { // Draw the selection partway between the tabs View nextTitle = getChildAt(mSelectedPosition + 1); left = (int) (mSelectionOffset * nextTitle.getLeft() + (1.0f - mSelectionOffset) * left); right = (int) (mSelectionOffset * nextTitle.getRight() + (1.0f - mSelectionOffset) * right); } } else { left = right = -1; } setIndicatorPosition(left, right); }

Y lo peor es que el campo SlidingTabStrip en TabLayout es privado y final.

private final SlidingTabStrip mTabStrip;

No veo cómo es posible lograr lo que necesita sin crear TabLayout totalmente nuevo.


Puedes hacerlo usando estilos.

En el diseño xml:

<android.support.design.widget.TabLayout android:id="@+id/tabs" style="@style/AppTabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" />

en el styles.xml:

<style name="AppTabLayout" parent="Widget.Design.TabLayout"> <item name="android:layout_marginLeft">40dp</item> <item name="android:layout_marginRight">40dp</item> </style>


Una solución simple es:

tabLayout.setTabIndicatorFullWidth(false);

Pero funciona con la última dependencia como

implementation ''com.android.support.constraint:constraint-layout:1.1.2'' implementation ''com.android.support:design:28.0.0''


Si no necesita que la tira sea más pequeña que el texto, esto debería funcionar:

public static void reduceMarginsInTabs(TabLayout tabLayout, int marginOffset) { View tabStrip = tabLayout.getChildAt(0); if (tabStrip instanceof ViewGroup) { ViewGroup tabStripGroup = (ViewGroup) tabStrip; for (int i = 0; i < ((ViewGroup) tabStrip).getChildCount(); i++) { View tabView = tabStripGroup.getChildAt(i); if (tabView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ((ViewGroup.MarginLayoutParams) tabView.getLayoutParams()).leftMargin = marginOffset; ((ViewGroup.MarginLayoutParams) tabView.getLayoutParams()).rightMargin = marginOffset; } } tabLayout.requestLayout(); } }

Para los puntos agregados puedes verificar el tamaño del texto de cada título.


, es posible ajustar el indicador de tabulación como relleno de configuración de título a 0

public void wrapTabIndicatorToTitle(TabLayout tabLayout, int externalMargin, int internalMargin) { View tabStrip = tabLayout.getChildAt(0); if (tabStrip instanceof ViewGroup) { ViewGroup tabStripGroup = (ViewGroup) tabStrip; int childCount = ((ViewGroup) tabStrip).getChildCount(); for (int i = 0; i < childCount; i++) { View tabView = tabStripGroup.getChildAt(i); //set minimum width to 0 for instead for small texts, indicator is not wrapped as expected tabView.setMinimumWidth(0); // set padding to 0 for wrapping indicator as title tabView.setPadding(0, tabView.getPaddingTop(), 0, tabView.getPaddingBottom()); // setting custom margin between tabs if (tabView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) tabView.getLayoutParams(); if (i == 0) { // left settingMargin(layoutParams, externalMargin, internalMargin); } else if (i == childCount - 1) { // right settingMargin(layoutParams, internalMargin, externalMargin); } else { // internal settingMargin(layoutParams, internalMargin, internalMargin); } } } tabLayout.requestLayout(); } } private void settingMargin(ViewGroup.MarginLayoutParams layoutParams, int start, int end) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { layoutParams.setMarginStart(start); layoutParams.setMarginEnd(end); layoutParams.leftMargin = start; layoutParams.rightMargin = end; } else { layoutParams.leftMargin = start; layoutParams.rightMargin = end; } }

EDITAR : A partir de com.android.support:design:28.0.0 , puede ajustar el indicador como etiqueta fácilmente ahora:

app:tabIndicatorFullWidth="false"