web-dev-qa-db-fra.com

Onglet personnalisé (avec la flèche vers le bas comme indicateur)

 enter image description here

Y at-il un wat pour faire un indicateur comme celui-ci?
a-t-il une flèche pointée vers le bas, comme dans l'élément sélectionné? 

12
Charles Galvez

La seule solution que j'ai pu trouver est de récupérer le code source de la TabLayout originale et de le personnaliser en fonction de vos besoins.

En fait, tout ce que vous avez à faire pour obtenir cette flèche de pointage personnalisée consiste à remplacer la méthode SlidingTabStrip's void draw(Canvas canvas). Malheureusement, SlidingTabStrip est private classe intérieure à l'intérieur de TabLayout.

 enter image description here

Heureusement, tout le code de la bibliothèque de support est ouvert, nous pouvons donc créer notre propre classe TabLayoutWithArrow. J'ai remplacé le void draw(Canvas canvas) standard par celui-ci pour dessiner la flèche:

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

Bien sûr, l’arrière-plan, la conception particulière de l’indicateur peuvent être améliorés/ajustés en fonction de vos besoins.

Pour personnaliser TabLayoutWithArrow, je devais copier ces fichiers dans mon projet:

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

Pour que la transparence soit derrière la flèche, il vous suffit de définir cette Shape-drawable, en tant que background pour la 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>

Et l'utilisation réelle est:

<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"/>

J'ai téléchargé l'ensemble du projet (l'application TabLayoutWithArrow + une page qui l'utilise) dans ma liste déroulante - n'hésitez pas à le consulter .

J'espère que ça aide

17
Konstantin Loginov

maintenant, cela ne fonctionne pas, la classe tintmanager est supprimée de la bibliothèque de support 23.2.0, j'ai géré la même fonctionnalité en modifiant l'arrière-plan dessinable au moment de l'exécution pour la détection de la position cliquée, PS: vérifiez cette question et répondez, j'utilise la même bibliothèque: https://github.com/astuetz/PagerSlidingTabStrip/issues/141

1
geniushkg

Voici le code pour toute personne nécessitant un triangle ascendant avec le code @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;
    }
0
Aditi