【问题标题】:how to customize Tab indicator width ?如何自定义 Tab 指示器宽度?
【发布时间】:2021-03-12 12:37:33
【问题描述】:

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

【问题讨论】:

  • 在您的可绘制文件夹中添加指标图像。
  • 查看我最新的解决方案:stackoverflow.com/a/58381087/7054052>

标签: android


【解决方案1】:

有一种更简单的方法可以实现这一点,只需将您的自定义指标的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】:

    试试这个:

    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文件中设置view pager后添加:

    wrapTabIndicatorToTitle(tabLayout,80,80);
    

    【讨论】:

    • 是的,通过这个解决方案,我得到标签标题宽度指示器,但我希望从左侧和右侧填充,指示器应该像图像一样位于中间
    • 您可以尝试将此值增加到 100 或仅使用自定义选项卡.. textview 和 view.. 您需要该解决方案吗?
    【解决方案3】:

    一个简单的解决方案是:

    tabLayout.setTabIndicatorFullWidth(false);
    

    但它适用于最新的依赖项,例如

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

    【讨论】:

    • 这将使指标宽度与我测试中的文本宽度相同。
    【解决方案4】:

    对于支持库版本 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);
    

    【讨论】:

      猜你喜欢
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 2021-06-09
      • 2019-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多