Пользовательский индикатор вкладки (со стрелкой вниз, как индикатор)

введите описание изображения здесь

Есть ли ват, чтобы сделать такой индикатор?
у него есть указательная стрелка вниз, как в выбранном элементе?

Ответ 1

Единственное решение, которое я смог найти, это захватить исходный код оригинального TabLayout и настроить его в соответствии с вашими потребностями.

Фактически, все, что вам нужно сделать, чтобы получить эту настраиваемую стрелку указателя, это переопределить метод SlidingTabStrip void draw(Canvas canvas). К сожалению, SlidingTabStrip является внутренним классом private внутри TabLayout.

введите описание изображения здесь

К счастью, весь код библиотеки поддержки открыт, поэтому мы можем создать собственный класс 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;
        }

Конечно, фон, конкретный дизайн индикатора можно улучшить/настроить в соответствии с вашими потребностями.

Чтобы создать свой пользовательский TabLayoutWithArrow, мне пришлось копировать эти файлы в свой проект:

  • AnimationUtils
  • TabLayout
  • ThemeUtils
  • ValueAnimatorCompat
  • ValueAnimatorCompatImplEclairMr1
  • ValueAnimatorCompatImplHoneycombMr1
  • ViewUtils
  • ViewUtilsLollipop

Чтобы иметь прозрачность за стрелкой, вам просто нужно установить этот Shape - drawable, как background для 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 - не стесняйтесь проверить его.

Надеюсь, это поможет

Ответ 2

теперь это не сработает, класс tintmanager удален из библиотеки поддержки 23.2.0, мне удалось использовать те же функциональные возможности, изменив фоновый рисунок во время выполнения внутри для обнаружения петли по петле, PS: проверьте этот вопрос и ответ. Я использую одну и ту же библиотеку: https://github.com/astuetz/PagerSlidingTabStrip/issues/141

Ответ 3

Вот код для тех, кому нужен восходящий треугольник с использованием кода @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)+getHeight()/4;
        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();


        path.close();

        return path;
    }