Come fare un indicatore della pagina per recyclerview orizzontale
Qualsiasi idea di come creare un indicatore della pagina per la lista recyclerview?
Come fare un indicatore della pagina per recyclerview orizzontale
Qualsiasi idea di come creare un indicatore della pagina per la lista recyclerview?
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);
}
}
È 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
C'è anche una post sul blog che fornisce maggiori dettagli su come funziona la decorazione here e il codice sorgente completo è available at GitHub
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
@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. –
così male devo fare un altro indicatore o riciclo che continuo a cambiare in base allo scroll del mio riciclatore principale, giusto? – ViVekH
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
@ shoban, come posso mostrare verticalmente.Verificare questo link https://stackoverflow.com/questions/47708974/create-custom-scroll-bar-in-android-wear-2-0 – kavie
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 !!!!!
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);
è solo un campione – Nima
hai trovato qualche anima fino ad ora ?? – Ramz