如何自定义Tab指标宽度?

时间:2018-04-13 07:15:12

标签: android

我想要这种类型的标签指示器我是如何实现这一点的,我已经尝试了所有具有可绘制可选处理程序但没有得到任何东西的解决方案

enter image description here

4 个答案:

答案 0 :(得分:4)

试试这个:

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);
    } else {
        layoutParams.leftMargin = start;
        layoutParams.rightMargin = end;
    }
}

在java文件中设置视图寻呼机后添加:

wrapTabIndicatorToTitle(tabLayout,80,80);

答案 1 :(得分:3)

有一种更简单的方法来实现这一点,只需向 drawable 提供自定义指示器的 app:tabIndicator

例如,在这种情况下:

underline.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <item android:gravity="center">
        <shape>
            <size
                android:width="22dp"
                android:height="2dp" />

            <corners android:radius="2dp" />

            <solid android:color="#FF0000" />
        </shape>
    </item>
</layer-list>

并以这种方式将其添加到您的 TabLayout

<com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/_16dp"
        android:layout_marginTop="@dimen/_16dp"
        app:tabIndicator="@drawable/underline"
        app:tabIndicatorColor="@color/offers_header_text"
        app:tabIndicatorHeight="4dp"
        app:tabMode="scrollable"
        app:tabRippleColor="@null" />

答案 2 :(得分:1)

一个简单的解决方案是:

tabLayout.setTabIndicatorFullWidth(false);

但是它可以与最新的依赖项一起使用

implementation 'com.google.android.material:material:1.0.0'

答案 3 :(得分:0)

对于版本28.0.0的支持库,我提出了一种解决方案,该解决方案将TabLayout.tabViewContentBounds对象替换为自定义对象,以便您可以在此处应用您的逻辑以随时更改指标位置

这是自定义RectF类(感谢您,这不是最终课程)

public class TabIndicatorRectF extends RectF implements Serializable {
    private RectF temp = new RectF();
    private IndicatorBoundsModifier indicatorBoundsModifier;

    public TabIndicatorRectF(IndicatorBoundsModifier indicatorBoundsModifier) {
        this.indicatorBoundsModifier = indicatorBoundsModifier;
    }

    private interface IndicatorBoundsModifier {
        void modify(RectF bounds);
    }

    @Override
    public void set(float left, float top, float right, float bottom) {
        temp.set(left, top, right, bottom);
        indicatorBoundsModifier.modify(temp);

        super.set(temp);
    }

    public void replaceBoundsRectF(TabLayout tabLayout) {
        try {
            Field field = TabLayout.class.getDeclaredField("tabViewContentBounds");
            field.setAccessible(true);
            field.set(tabLayout, this);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    public static class FixedWidthModifier implements IndicatorBoundsModifier {
        private float halfWidth;

        public FixedWidthModifier(float width) {
            this.halfWidth = Math.abs(width) / 2;
        }

        @Override
        public void modify(RectF bounds) {
            float centerX = bounds.centerX();
            bounds.left = centerX - halfWidth;
            bounds.right = centerX + halfWidth;
        }
    }

}

现在叫这个

new TabIndicatorRectF(
            new TabIndicatorRectF.FixedWidthModifier(
                    getResources().getDimension(R.dimen.tab_indicator_width)))
            .replaceBoundsRectF(tabLayout);