Android标签布局:相对于标签标题包裹标签指示符宽度

是否有任何方法可以相对于标题标题包裹标签指示符宽度?

当前

需要

Solutions Collecting From Web of "Android标签布局:相对于标签标题包裹标签指示符宽度"

是的 ,可以将标签指示器作为标题设置填充包装为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; } } 

结果

在此处输入图像描述

如果您不需要条带小于文本,那么这应该工作:

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

对于添加的点,您可以检查每个标题的文本大小。

简短的回答是“不”。 这是解释。

SlidingTabStrip有私有类SlidingTabStrip绘制指标

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

我相信mIndicatorLeft和mIndicatorRight是你所需要的。 这些字段设置在同一个类中:

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

其中左右参数在下一个方法中计算:

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

最糟糕的是TabLayout中的SlidingTabStrip字段是私有的和最终的。

 private final SlidingTabStrip mTabStrip; 

我没有看到如何在不创建全新TabLayout的情况下实现您的需求。

我注意到需要的SDK版本,但您可以直接在XML文件中执行,使用app namespace添加padding属性。

只需让你的TabLayout看起来像这样:

   

您也可以为您的父母布局移动xmlns:app="http://schemas.android.com/apk/res-auto" ,但它是您的选择:)

感谢leon的回答,这引导我通过XML实现这一目标。

我尝试了2个小时的各种解决方案,但没有一个有完美的效果。
问题出在tabView的填充上 – 即使我将其填充设置为全0,
不同的选项卡仍然具有不同的填充,因此其TextView内的文本大小不同。

然后我find了这个完美解决它的库。
https://github.com/H07000223/FlycoTabLayout
正如@Stas Melnychenko所说,除非我们重新编写TabLayout ,否则我们可能无法做到。 这个库确实重写了一个TabLayout ……

你可以使用样式来做到这一点。

在布局xml中:

  

在styles.xml中:

  

相对于标签标题包裹标签指示符宽度,并使用标签标题添加右边距,使用标签指示符添加右边距。

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