Répondre

0

Vous devez d'abord créer un autre RecyclerView pour les cercles et placer ce code dans OnScrollListener du premier RecyclerView.

int[] firstVisibleItemPositions = new int[appList.size()]; 
int[] lastVisibleItemPositions = new int[appList.size()]; 

int position = ((StaggeredGridLayoutManager) listView.getLayoutManager()).findFirstVisibleItemPositions(firstVisibleItemPositions)[0]; 
View currentView = circlesList.getChildAt(position); 
int lastPosition = ((StaggeredGridLayoutManager) listView.getLayoutManager()).findLastVisibleItemPositions(lastVisibleItemPositions)[0]; 
View lastView = circlesList.getChildAt(lastPosition); 
ImageView circle; 
if (dx>0) { 
    if (currentView != null && lastPosition != position) { 
     circle = (ImageView) currentView.findViewById(R.id.img); 
     circle.setImageResource(R.drawable.empty_circle); 
    } 
    if (lastView != null && lastPosition != position) { 
     circle = (ImageView) lastView.findViewById(R.id.img); 
     circle.setImageResource(R.drawable.selected_circle); 
    } 
}else if (dx<0){ 
    if (currentView != null && lastPosition != position) { 
     circle = (ImageView) currentView.findViewById(R.id.img); 
     circle.setImageResource(R.drawable.selected_circle); 
    } 
    if (lastView != null && lastPosition != position) { 
     circle = (ImageView) lastView.findViewById(R.id.img); 
     circle.setImageResource(R.drawable.empty_circle); 
    } 
} 
3

Vous pouvez ajouter un indicateur en utilisant RecyclerView.ItemDecoration. Dessinez simplement des lignes ou des cercles dans le bas et utilisez layoutManager.findFirstVisibleItemPosition() pour obtenir l'élément actif actuel.

Étant donné que les pagers ont tendance à remplir toute la largeur, il s'agit d'une façon courante d'obtenir l'élément affiché. Cela nous permet également de calculer la distance de défilement en comparant le bord gauche de l'enfant aux parents.

Ci-dessous vous trouverez une décoration exemple qui dessine quelques lignes et anime entre eux

public class LinePagerIndicatorDecoration extends RecyclerView.ItemDecoration { 

    private int colorActive = 0xFFFFFFFF; 
    private int colorInactive = 0x66FFFFFF; 

    private static final float DP = Resources.getSystem().getDisplayMetrics().density; 

    /** 
    * Height of the space the indicator takes up at the bottom of the view. 
    */ 
    private final int mIndicatorHeight = (int) (DP * 16); 

    /** 
    * Indicator stroke width. 
    */ 
    private final float mIndicatorStrokeWidth = DP * 2; 

    /** 
    * Indicator width. 
    */ 
    private final float mIndicatorItemLength = DP * 16; 
    /** 
    * Padding between indicators. 
    */ 
    private final float mIndicatorItemPadding = DP * 4; 

    /** 
    * Some more natural animation interpolation 
    */ 
    private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); 

    private final Paint mPaint = new Paint(); 

    public LinePagerIndicatorDecoration() { 
    mPaint.setStrokeCap(Paint.Cap.ROUND); 
    mPaint.setStrokeWidth(mIndicatorStrokeWidth); 
    mPaint.setStyle(Paint.Style.STROKE); 
    mPaint.setAntiAlias(true); 
    } 

    @Override 
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 
    super.onDrawOver(c, parent, state); 

    int itemCount = parent.getAdapter().getItemCount(); 

    // center horizontally, calculate width and subtract half from center 
    float totalLength = mIndicatorItemLength * itemCount; 
    float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding; 
    float indicatorTotalWidth = totalLength + paddingBetweenItems; 
    float indicatorStartX = (parent.getWidth() - indicatorTotalWidth)/2F; 

    // center vertically in the allotted space 
    float indicatorPosY = parent.getHeight() - mIndicatorHeight/2F; 

    drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount); 


    // find active page (which should be highlighted) 
    LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); 
    int activePosition = layoutManager.findFirstVisibleItemPosition(); 
    if (activePosition == RecyclerView.NO_POSITION) { 
     return; 
    } 

    // find offset of active page (if the user is scrolling) 
    final View activeChild = layoutManager.findViewByPosition(activePosition); 
    int left = activeChild.getLeft(); 
    int width = activeChild.getWidth(); 

    // on swipe the active item will be positioned from [-width, 0] 
    // interpolate offset for smooth animation 
    float progress = mInterpolator.getInterpolation(left * -1/(float) width); 

    drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress, itemCount); 
    } 

    private void drawInactiveIndicators(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) { 
    mPaint.setColor(colorInactive); 

    // width of item indicator including padding 
    final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

    float start = indicatorStartX; 
    for (int i = 0; i < itemCount; i++) { 
     // draw the line for every item 
     c.drawLine(start, indicatorPosY, start + mIndicatorItemLength, indicatorPosY, mPaint); 
     start += itemWidth; 
    } 
    } 

    private void drawHighlights(Canvas c, float indicatorStartX, float indicatorPosY, 
           int highlightPosition, float progress, int itemCount) { 
    mPaint.setColor(colorActive); 

    // width of item indicator including padding 
    final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

    if (progress == 0F) { 
     // no swipe, draw a normal indicator 
     float highlightStart = indicatorStartX + itemWidth * highlightPosition; 
     c.drawLine(highlightStart, indicatorPosY, 
      highlightStart + mIndicatorItemLength, indicatorPosY, mPaint); 
    } else { 
     float highlightStart = indicatorStartX + itemWidth * highlightPosition; 
     // calculate partial highlight 
     float partialLength = mIndicatorItemLength * progress; 

     // draw the cut off highlight 
     c.drawLine(highlightStart + partialLength, indicatorPosY, 
      highlightStart + mIndicatorItemLength, indicatorPosY, mPaint); 

     // draw the highlight overlapping to the next item as well 
     if (highlightPosition < itemCount - 1) { 
     highlightStart += itemWidth; 
     c.drawLine(highlightStart, indicatorPosY, 
      highlightStart + partialLength, indicatorPosY, mPaint); 
     } 
    } 
    } 

    @Override 
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
    super.getItemOffsets(outRect, view, parent, state); 
    outRect.bottom = mIndicatorHeight; 
    } 
} 

Ce qui vous donnera un résultat comme le

suivant

pager indicator


Il y a aussi un article de blog qui va plus en détail sur la façon dont la décoration fonctionne here et le code source complet est available at GitHub

+0

donc j'ai un recyclerview avec une grille 3x3, quand les éléments dépassent le 3x3 il va à la page suivante et ainsi de suite, comme si https://i.stack.imgur.com/JYPu7.gif, im demandant parce que vous avez mentionné "assurez-vous que les mises en page ont layout_width = 'match_parent'" – ViVekH

+1

@ViVekH Heh, je regardais juste votre question quand vous avez commenté ... Rien de ce qui précède s'applique à votre cas d'utilisation. Le paramètre match_parent est tel que l'indicateur dessine correctement (pour calculer le défilement) et il est destiné à une configuration de type ViewPager. –

+0

si mal à faire un autre indicateur ou recyclerview que je continue à changer selon le défilement de mon recycleur principal droit? – ViVekH

0

J'ai copié la même réponse que celle donnée par David Medenjak, mais pour faire les cercles sous le reclassement. J'ai mis à jour quelques lignes de code dans la réponse ci-dessus, s'il vous plaît jeter un oeil et utiliser en conséquence.

/** 
* Created by shobhan on 4/10/17. 
*/ 

public class CirclePagerIndicatorDecoration extends RecyclerView.ItemDecoration { 

    private int colorActive = 0x727272; 
    private int colorInactive = 0xF44336; 

    private static final float DP = Resources.getSystem().getDisplayMetrics().density; 

    /** 
    * Height of the space the indicator takes up at the bottom of the view. 
    */ 
    private final int mIndicatorHeight = (int) (DP * 16); 

    /** 
    * Indicator stroke width. 
    */ 
    private final float mIndicatorStrokeWidth = DP * 2; 

    /** 
    * Indicator width. 
    */ 
    private final float mIndicatorItemLength = DP * 16; 
    /** 
    * Padding between indicators. 
    */ 
    private final float mIndicatorItemPadding = DP * 4; 

    /** 
    * Some more natural animation interpolation 
    */ 
    private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); 

    private final Paint mPaint = new Paint(); 

    public CirclePagerIndicatorDecoration() { 
     mPaint.setStrokeCap(Paint.Cap.ROUND); 
     mPaint.setStrokeWidth(mIndicatorStrokeWidth); 
     mPaint.setStyle(Paint.Style.FILL); 
     mPaint.setAntiAlias(true); 
    } 

    @Override 
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 
     super.onDrawOver(c, parent, state); 

     int itemCount = parent.getAdapter().getItemCount(); 

     // center horizontally, calculate width and subtract half from center 
     float totalLength = mIndicatorItemLength * itemCount; 
     float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding; 
     float indicatorTotalWidth = totalLength + paddingBetweenItems; 
     float indicatorStartX = (parent.getWidth() - indicatorTotalWidth)/2F; 

     // center vertically in the allotted space 
     float indicatorPosY = parent.getHeight() - mIndicatorHeight/2F; 

     drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount); 


     // find active page (which should be highlighted) 
     LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); 
     int activePosition = layoutManager.findFirstVisibleItemPosition(); 
     if (activePosition == RecyclerView.NO_POSITION) { 
      return; 
     } 

     // find offset of active page (if the user is scrolling) 
     final View activeChild = layoutManager.findViewByPosition(activePosition); 
     int left = activeChild.getLeft(); 
     int width = activeChild.getWidth(); 

     // on swipe the active item will be positioned from [-width, 0] 
     // interpolate offset for smooth animation 
     float progress = mInterpolator.getInterpolation(left * -1/(float) width); 

     drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress, itemCount); 
    } 

    private void drawInactiveIndicators(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) { 
     mPaint.setColor(Color.GRAY); 

     // width of item indicator including padding 
     final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

     float start = indicatorStartX; 
     for (int i = 0; i < itemCount; i++) { 
      // draw the line for every item 
      c.drawCircle(start + mIndicatorItemLength,indicatorPosY,itemWidth/6,mPaint); 
      // c.drawLine(start, indicatorPosY, start + mIndicatorItemLength, indicatorPosY, mPaint); 
      start += itemWidth; 
     } 
    } 

    private void drawHighlights(Canvas c, float indicatorStartX, float indicatorPosY, 
           int highlightPosition, float progress, int itemCount) { 
     mPaint.setColor(Color.RED); 

     // width of item indicator including padding 
     final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

     if (progress == 0F) { 
      // no swipe, draw a normal indicator 
      float highlightStart = indicatorStartX + itemWidth * highlightPosition; 
     /* c.drawLine(highlightStart, indicatorPosY, 
        highlightStart + mIndicatorItemLength, indicatorPosY, mPaint); 
     */ 
      c.drawCircle(highlightStart,indicatorPosY,itemWidth/6,mPaint); 

     } else { 
      float highlightStart = indicatorStartX + itemWidth * highlightPosition; 
      // calculate partial highlight 
      float partialLength = mIndicatorItemLength * progress; 
      c.drawCircle(highlightStart + mIndicatorItemLength,indicatorPosY,itemWidth/6,mPaint); 

      // draw the cut off highlight 
      /* c.drawLine(highlightStart + partialLength, indicatorPosY, 
        highlightStart + mIndicatorItemLength, indicatorPosY, mPaint); 
*/ 
      // draw the highlight overlapping to the next item as well 
      /* if (highlightPosition < itemCount - 1) { 
       highlightStart += itemWidth; 
       *//*c.drawLine(highlightStart, indicatorPosY, 
         highlightStart + partialLength, indicatorPosY, mPaint);*//* 
       c.drawCircle(highlightStart ,indicatorPosY,itemWidth/4,mPaint); 

      }*/ 
     } 
    } 

    @Override 
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
     super.getItemOffsets(outRect, view, parent, state); 
     outRect.bottom = mIndicatorHeight; 
    } 
} 

et l'appliquer à la recyclerview comme suit

+0

@ shoban, comment puis-je montrer verticalement.Veuillez vérifier ce lien https://stackoverflow.com/questions/47708974/create-custom-scroll-bar-in-android-wear-2-0 – kavie

0

J'ai changé le code pour les cercles. Supprimé le code pour dessiner la ligne et la même chose est remplacée par des méthodes de cercle de dessin. S'il vous plaît trouverez ci-dessous la classe complète:

CirclePagerIndicatorDecoration public class étend RecyclerView.ItemDecoration {private int colorActive = 0xDE000000; private int colorInactive = 0x33000000;

private static final float DP = Resources.getSystem().getDisplayMetrics().density; 

/** 
* Height of the space the indicator takes up at the bottom of the view. 
*/ 
private final int mIndicatorHeight = (int) (DP * 16); 

/** 
* Indicator stroke width. 
*/ 
private final float mIndicatorStrokeWidth = DP * 4; 

/** 
* Indicator width. 
*/ 
private final float mIndicatorItemLength = DP * 4; 
/** 
* Padding between indicators. 
*/ 
private final float mIndicatorItemPadding = DP * 8; 

/** 
* Some more natural animation interpolation 
*/ 
private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator(); 

private final Paint mPaint = new Paint(); 

public CirclePagerIndicatorDecoration() { 

    mPaint.setStrokeWidth(mIndicatorStrokeWidth); 
    mPaint.setStyle(Paint.Style.STROKE); 
    mPaint.setAntiAlias(true); 
} 

@Override 
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { 
    super.onDrawOver(c, parent, state); 

    int itemCount = parent.getAdapter().getItemCount(); 

    // center horizontally, calculate width and subtract half from center 
    float totalLength = mIndicatorItemLength * itemCount; 
    float paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding; 
    float indicatorTotalWidth = totalLength + paddingBetweenItems; 
    float indicatorStartX = (parent.getWidth() - indicatorTotalWidth)/2F; 

    // center vertically in the allotted space 
    float indicatorPosY = parent.getHeight() - mIndicatorHeight/2F; 

    drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount); 

    // find active page (which should be highlighted) 
    LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); 
    int activePosition = layoutManager.findFirstVisibleItemPosition(); 
    if (activePosition == RecyclerView.NO_POSITION) { 
     return; 
    } 

    // find offset of active page (if the user is scrolling) 
    final View activeChild = layoutManager.findViewByPosition(activePosition); 
    int left = activeChild.getLeft(); 
    int width = activeChild.getWidth(); 
    int right = activeChild.getRight(); 

    // on swipe the active item will be positioned from [-width, 0] 
    // interpolate offset for smooth animation 
    float progress = mInterpolator.getInterpolation(left * -1/(float) width); 

    drawHighlights(c, indicatorStartX, indicatorPosY, activePosition, progress); 
} 

private void drawInactiveIndicators(Canvas c, float indicatorStartX, float indicatorPosY, int itemCount) { 
    mPaint.setColor(colorInactive); 

    // width of item indicator including padding 
    final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

    float start = indicatorStartX; 
    for (int i = 0; i < itemCount; i++) { 

     c.drawCircle(start, indicatorPosY, mIndicatorItemLength/2F, mPaint); 

     start += itemWidth; 
    } 
} 

private void drawHighlights(Canvas c, float indicatorStartX, float indicatorPosY, 
          int highlightPosition, float progress) { 
    mPaint.setColor(colorActive); 

    // width of item indicator including padding 
    final float itemWidth = mIndicatorItemLength + mIndicatorItemPadding; 

    if (progress == 0F) { 
     // no swipe, draw a normal indicator 
     float highlightStart = indicatorStartX + itemWidth * highlightPosition; 

     c.drawCircle(highlightStart, indicatorPosY, mIndicatorItemLength/2F, mPaint); 

    } else { 
     float highlightStart = indicatorStartX + itemWidth * highlightPosition; 
     // calculate partial highlight 
     float partialLength = mIndicatorItemLength * progress + mIndicatorItemPadding*progress; 

     c.drawCircle(highlightStart + partialLength, indicatorPosY, mIndicatorItemLength/2F, mPaint); 
    } 
} 

@Override 
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 
    super.getItemOffsets(outRect, view, parent, state); 
    outRect.bottom = mIndicatorHeight; 
} 

}

Merci beaucoup, LB Gupta Bonne programmation !!!!!

0

En cas de besoin, j'ai écrit ma propre bibliothèque pour cela (après beaucoup de recherche): RecyclerView indicator. Voici comment vous le faites:

<com.kingfisher.easyviewindicator.RecyclerViewIndicator 
    android:id="@+id/circleIndicator" 
    android:layout_width="match_parent" 
    android:layout_height="20dp" 
    app:avi_animation_enable="true" 
    app:avi_drawable="@drawable/blue_radius" 
    app:avi_drawable_unselected="@drawable/gray_radius" 
    app:avi_height="10dp" 
    app:avi_margin="10dp" 
    app:avi_width="10dp" 
    app:layout_constraintTop_toBottomOf="@+id/recyclerView"> 

</com.kingfisher.easyviewindicator.RecyclerViewIndicator> 
// In code: 
recyclerView.setAdapter(new TestAdapter()); 
recyclerViewIndicator.setRecyclerView(recyclerView);