自定义选项卡指示器(带有向下箭头的指示器)

16

在此输入图片描述

是否有一种方法可以创建类似这样的指示器?
它具有像所选项目中那样的向下指向的箭头?

3个回答

21

我找到的唯一解决方案是获取原始TabLayout的源代码并按需自定义。

事实上,您所需做的就是覆盖SlidingTabStripvoid draw(Canvas canvas)方法即可获得此自定义指向箭头。不幸的是,SlidingTabStripTabLayout内部的private内部类。

enter image description here

幸运的是,所有支持库代码都是开源的,因此我们可以创建自己的TabLayoutWithArrow类。我用以下方法替换了标准的void draw(Canvas canvas)以绘制箭头:
        @Override
        public void draw(Canvas canvas) {
            super.draw(canvas);
            // i used <dimen name="pointing_arrow_size">3dp</dimen>
            int arrowSize = getResources().getDimensionPixelSize(R.dimen.pointing_arrow_size);

            if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
                canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight - arrowSize,
                        mIndicatorRight, getHeight() - arrowSize, mSelectedIndicatorPaint);
                canvas.drawPath(getTrianglePath(arrowSize), mSelectedIndicatorPaint);
            }
        }

        private Path getTrianglePath(int arrowSize) {
            mSelectedIndicatorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mSelectedIndicatorPaint.setAntiAlias(true);

            int leftPointX = mIndicatorLeft + (mIndicatorRight - mIndicatorLeft) / 2 - arrowSize*2;
            int rightPointX = leftPointX + arrowSize*2;
            int bottomPointX = leftPointX + arrowSize;
            int leftPointY = getHeight() - arrowSize;
            int bottomPointY = getHeight();

            Point left = new Point(leftPointX, leftPointY);
            Point right = new Point(rightPointX, leftPointY);
            Point bottom = new Point(bottomPointX, bottomPointY);

            Path path = new Path();
            path.setFillType(Path.FillType.EVEN_ODD);
            path.setLastPoint(left.x, left.y);
            path.lineTo(right.x, right.y);
            path.lineTo(bottom.x, bottom.y);
            path.lineTo(left.x, left.y);
            path.close();

            return path;
        }

Of course,背景和指示器的设计可以根据您的需求进行改进/调整。
为了制作我的自定义TabLayoutWithArrow,我不得不将这些文件复制到我的项目中:
- AnimationUtils - TabLayout - ThemeUtils - ValueAnimatorCompat - ValueAnimatorCompatImplEclairMr1 - ValueAnimatorCompatImplHoneycombMr1 - ViewUtils - ViewUtilsLollipop 为了在箭头后面实现透明度,您只需要将这个Shape-drawable作为TabLayoutWithArrow的背景即可。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:bottom="@dimen/pointing_arrow_size">
        <shape android:shape="rectangle" >
            <solid android:color="#FFFF00" />
        </shape>
    </item>
    <item android:height="@dimen/pointing_arrow_size"
        android:gravity="bottom">
        <shape android:shape="rectangle" >
            <solid android:color="#00000000" />
        </shape>
    </item>
</layer-list>

实际使用方法为:

<klogi.com.viewpagerwithdifferentmenu.CustomTabLayout.TabLayoutWithArrow
    android:id="@+id/tabLayout"
    android:background="@drawable/tab_layout_background"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

我已经将整个项目(包括使用TabLayoutWithArrow的单页面应用程序)上传到我的Dropbox中 - 随意查看
希望这能有所帮助。

它运行良好,我们如何增加指示器的高度? - Jaydeep
你找到了逆转三角形的方法吗? - Aditi

1

现在它不起作用了,tintmanager类已从支持库23.2.0中删除,我通过在for循环内检测点击位置并在运行时更改背景drawable来管理相同的功能。PS:请查看此问题和答案,我正在使用相同的库:https://github.com/astuetz/PagerSlidingTabStrip/issues/141


1

以下是代码,供需要使用 Konstantin Loginov 代码实现上升三角的人使用:

private Path getTrianglePath(int arrowSize) {

        mSelectedIndicatorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mSelectedIndicatorPaint.setAntiAlias(true);
        mSelectedIndicatorPaint.setColor(Color.WHITE);

        int leftPointX = mIndicatorLeft + (mIndicatorRight - mIndicatorLeft) / 2 - arrowSize * 1 / 2;
        int mTopX = leftPointX + arrowSize;
        int mTopY = getHeight() - arrowSize;
        int rightPointX = leftPointX + arrowSize * 2;

        int leftPointY = getHeight();

        Point left = new Point(leftPointX, leftPointY);
        Point right = new Point(rightPointX, leftPointY);
        Point bottom = new Point(mTopX, mTopY);

        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);
        path.setLastPoint(left.x, left.y);
        path.lineTo(right.x, right.y);
        path.lineTo(bottom.x, bottom.y);
        path.lineTo(left.x, left.y);
        path.close();

        return path;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接