如何制作卧式recyclerview的页面指示器 [英] How to make a page indicator for horizontal recyclerview
问题描述
任何想法如何为recyclerview列表创建页面指示器吗?
Any idea how to create a page indicator for recyclerview list ?
推荐答案
您可以使用RecyclerView.ItemDecoration添加指标.
You can add an indicator by using RecyclerView.ItemDecoration.
只需在底部绘制一些线或圆,然后使用layoutManager.findFirstVisibleItemPosition()
获取当前活动项目.由于传呼机往往会填满整个宽度,因此这是获取所显示项目的一种正确方法.这也使我们可以通过将孩子的左边缘与父母的边缘进行比较来计算滚动距离.
Just draw some lines or circles at the bottom and use layoutManager.findFirstVisibleItemPosition()
to get the current active item. Since pagers tend to fill the whole width this is an accruate way of getting the displayed item. This also allows us to calculate the scrolling distance by comparing the childs left edge to the parents.
下面您将找到一个示例装饰,该装饰在它们之间绘制了一些线条并设置了动画
Below you find a sample decoration that draws some lines and animates between them
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;
}
}
哪个会给您以下结果
还有一篇博客文章,详细介绍了装饰的工作方式在GitHub上可用
There is also a blog post that goes more into detail about how the decoration works here and the full source code is available at GitHub
这篇关于如何制作卧式recyclerview的页面指示器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!