risposta

0

Per prima cosa è necessario creare un altro RecyclerView per le cerchie e inserire questo codice in OnScrollListener del primo 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

È possibile aggiungere un indicatore utilizzando RecyclerView.ItemDecoration.

Basta disegnare alcune linee o cerchi nella parte inferiore e utilizzare layoutManager.findFirstVisibleItemPosition() per ottenere l'elemento attivo corrente. Poiché i cercapersone tendono a riempire l'intera larghezza, questo è un modo accu- ratato di ottenere l'oggetto visualizzato. Questo ci consente anche di calcolare la distanza di scorrimento confrontando il lato sinistro del bambino con i genitori.

Qui di seguito troverete una decorazione di esempio che richiama alcune linee e anima tra loro

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

che vi darà un risultato come il seguente

pager indicator


C'è anche una post sul blog che fornisce maggiori dettagli su come funziona la decorazione here e il codice sorgente completo è available at GitHub

+0

quindi ho un recyclerview con una griglia 3x3, quando gli articoli superano il 3x3 va alla pagina successiva e così via, come ad esempio https://i.stack.imgur.com/JYPu7.gif, sto chiedendo perché hai menzionato "assicurati che i layout degli articoli abbiano layout_width = 'match_parent'" – ViVekH

+1

@ViVekH Heh, stavo solo guardando la tua domanda quando hai commentato ... Nessuna delle precedenti si applica al tuo caso d'uso. Match_parent è in modo tale che l'indicatore si disegna correttamente (per calcolare lo scroll) ed è inteso per una configurazione simile a ViewPager. –

+0

così male devo fare un altro indicatore o riciclo che continuo a cambiare in base allo scroll del mio riciclatore principale, giusto? – ViVekH

0

Ho copiato la stessa risposta che viene data da David Medenjak, ma per creare i cerchi al di sotto del recyclerview. Ho aggiornato alcune righe di codice nella risposta di cui sopra, per favore dare un'occhiata e usare di conseguenza.

/** 
* 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; 
    } 
} 

e applicarlo alla recyclerview come segue

+0

@ shoban, come posso mostrare verticalmente.Verificare questo link https://stackoverflow.com/questions/47708974/create-custom-scroll-bar-in-android-wear-2-0 – kavie

0

ho cambiato il codice per i cerchi. Rimosso il codice per disegnare la linea e lo stesso viene sostituito con i metodi di disegnare cerchi. Di seguito riportiamo la classe completa:

public class CirclePagerIndicatorDecoration estende 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; 
} 

}

Molte grazie, LB Gupta Felice Coding !!!!!

0

in caso di necessità di chiunque, ho scritto la mia libreria per questo (dopo un sacco di ricerca): RecyclerView indicator. Ecco come lo fai:

<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); 
Problemi correlati