首先单个我们知道recyclerview翻页效果一般是配合viewPager来完成的 但是如何做到单个fragment无需viewPager也能完成操作呢!
这个时候就需要谷歌的官方推荐的SnapHelper 来完成这个需求 但是又有大神帮忙封装好了就直接拿来用就好哈哈
导入sdk implementation 'com.gcssloop.support:pagerlayoutmanager:1.3.1@aar'
LogUtils.i(TAG,"servicefragment 列表展示 数据大小:"+data.size());
final PagerGridLayoutManager pagerGridLayoutManager = new PagerGridLayoutManager(2, 8, PagerGridLayoutManager.HORIZONTAL);
pagerGridLayoutManager.setPageListener(this);
recycler_service.setLayoutManager(pagerGridLayoutManager);
PagerGridSnapHelper pagerGridSnapHelper = new PagerGridSnapHelper();
recycler_service.setOnFlingListener(null);
pagerGridSnapHelper.attachToRecyclerView(recycler_service);
// initTypeViewPager(2,8,list);
AllAppAdapter allAppAdapter = new AllAppAdapter(applicationContext, data);
recycler_service.setAdapter(allAppAdapter);
int dataPage = (int) Math.ceil((double)data.size() / 16); //(double)细节 如果是整数不会向上取整
LogUtils.i(TAG,"dataPage="+dataPage);
mIndicator.setPageNum(dataPage);
recycler_service.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int indexNum=2;
int prePageFirstPos = pagerGridLayoutManager.findPrePageFirstPos();
int indicatorIndex=0;
if (indexNum > 1) {
indicatorIndex = (prePageFirstPos / 8) % indexNum;
if (prePageFirstPos % 8 > 0) {
indicatorIndex = indicatorIndex == indexNum ? 0 : indicatorIndex + 1;
}
LogUtils.i(TAG,"addOnScrollListener-> indicatorIndex="+indicatorIndex);
mIndicator.onPageScrolled(2, 0.0f, recyclerView);
}
// mIndicator.onPageScrolled(indicatorIndex,0.0f,dx);
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
以上注意setOnFlingListener(null) 这个方法 必须设置为null 查看源码后发现有的时候会找不到recyclerview实例 导致崩溃的问题
下面是自定义指示器的代码 有点乱哈 没有优化的版本
public class SimpleLineIndicator extends View {
private static final String TAG ="SimpleCircleIndicator" ;
Paint circlePaint;
private int pageNum;
private float scrollPercent = 0f;
private int currentPosition;
private int gapSize;
private float radius;
private int colorOn;
private int colorOff;
public SimpleLineIndicator(Context context) {
super(context);
init();
}
public SimpleLineIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SimpleLineIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// radius = SystemUtils.dp2px( getContext(),3);/**/
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
colorOn = Color.WHITE;
colorOff = Color.parseColor("#888888");
// gapSize = SystemUtils.dp2px( getContext(),10);
circlePaint.setStrokeCap(Paint.Cap.ROUND);
circlePaint.setStrokeWidth(SystemUtils.dp2px(4));
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setAntiAlias(true);
}
public void setSelectDotColor(int colorOn) {
this.colorOn = colorOn;
}
public void setUnSelectDotColor(int colorOff) {
this.colorOff = colorOff;
}
private RecyclerView mRecyclerView;
public void onPageScrolled(int position, float percent, RecyclerView recyclerView) {
scrollPercent = percent;
currentPosition = position;
mRecyclerView=recyclerView;
invalidate();
}
private ViewPager viewPager;
public void setViewPager(ViewPager viewPager) {
this.viewPager = viewPager;
if (null != viewPager) {
pageNum = viewPager.getAdapter().getCount();
}
}
protected final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
private float mLongIndicatorItemLength=SystemUtils.dp2px(100);
private float mShortIndicatorItemLength=SystemUtils.dp2px(48);
private float mIndicatorItemPadding=SystemUtils.dp2px(24);
private int[] mPageScrolls;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (pageNum <= 0) {
return;
}
PagerGridLayoutManager layoutManager = (PagerGridLayoutManager) mRecyclerView.getLayoutManager();
if (layoutManager==null){
LogUtils.i(TAG,"layoutManager is null ");
return;
}
//计算 指示器长和短的长度和
float totalLength = mLongIndicatorItemLength + mShortIndicatorItemLength * (pageNum - 1);
//计算指示器外边距总距离
float paddingBetweenItems = Math.max(0, pageNum - 1) * mIndicatorItemPadding;
//指示器真正的长度
float indicatorTotalWidth = totalLength + paddingBetweenItems;
LogUtils.i(TAG,"onDraw totalLength="+totalLength+"---->paddingBetweenItems ="+paddingBetweenItems+"----->indicatorTotalWidth="+indicatorTotalWidth+"----->getWidth="+getWidth());
//x y 起始位置
float indicatorStartX;
float indicatorPosY;
indicatorStartX=(getWidth()-indicatorTotalWidth)/2F;
indicatorPosY=getHeight()-18;
float progress;
LogUtils.i(TAG,"onDraw startX="+indicatorStartX+"onDraw startY="+indicatorPosY);
int offsetX = layoutManager.getOffsetX();
int width = layoutManager.getWidth();
int currentPage=offsetX/width;
if (offsetX % width > 0){
currentPage+=1;
}
float f;
f = (layoutManager.getOffsetX() - currentPage * mRecyclerView.getWidth()) / (float) (mRecyclerView.getWidth());
progress=mInterpolator.getInterpolation(f);
int nextPage;
int pageSize = layoutManager.getItemCount();
mPageScrolls = new int[pageSize];
for (int i = 0; i < pageSize; i++) {
mPageScrolls[i]=layoutManager.getWidth()*i;
}
if (offsetX - mPageScrolls[currentPage] > 0) {
nextPage = currentPage + 1;
} else if (offsetX - mPageScrolls[currentPage] < 0) {
nextPage = currentPage - 1;
} else {
nextPage = currentPage;
}
LogUtils.i(TAG,"onDraw progress= "+progress +"---->offsetX="+offsetX+"---->pageSize="+pageSize+"----->nextPage="+nextPage);
//需要获取当前页 参数
drawInactiveIndicators(canvas, indicatorStartX, indicatorPosY, currentPage, progress, pageNum, nextPage);
//
// float left = (getWidth() - (pageNum - 1) * gapSize) * 0.5f;
// LogUtils.i(TAG,"onDraw ----> left="+left+"[getWidth="+getWidth()+"]");
// float height = getHeight() * 0.5f;
// LogUtils.i(TAG,"height="+height);
//
// circlePaint.setColor(colorOff);
// for (int i = 0; i < pageNum; i++) {
// canvas.drawLine(left + i * gapSize, height, left + i * gapSize+50,height, circlePaint);
//
// }
// circlePaint.setColor(colorOn);
// canvas.drawLine(left + currentPosition * gapSize + gapSize * scrollPercent, height, left + currentPosition * gapSize + gapSize * scrollPercent+50,height, circlePaint);
}
public void setPageNum(int nums){
pageNum = nums;
}
private void drawInactiveIndicators(Canvas c, float indicatorStartX, float indicatorPosY,
int highlightPosition, float progress, int pageCount, int nextPage) {
int blendColor = ColorUtils.blendARGB(colorOn, colorOff, progress);
int blendColor1 = ColorUtils.blendARGB(colorOn, colorOff, 1 - progress);
final float itemWidth = mLongIndicatorItemLength + mIndicatorItemPadding;
float start;
// if (canScrollHorizontally) {
start = indicatorStartX;
// } else {
// start = indicatorPosY;
// }
if (progress == 0F) {
for (int i = 0; i < pageCount; i++) {
if (i == highlightPosition) {
circlePaint.setColor(colorOn);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mLongIndicatorItemLength, indicatorPosY, circlePaint);
start += itemWidth;
LogUtils.i(TAG,"i==highlightPosition true----->start=" +start+"----->itemWidth="+itemWidth+"---->start + mLongIndicatorItemLength="+start + mLongIndicatorItemLength);
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mLongIndicatorItemLength, mPaint);
// start += itemWidth;
// }
} else {
circlePaint.setColor(colorOff);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mShortIndicatorItemLength, indicatorPosY, circlePaint);
start += mShortIndicatorItemLength + mIndicatorItemPadding;
LogUtils.i(TAG,"i==highlightPosition false----->start=" +start+"----->itemWidth="+itemWidth+"---->start + mShortIndicatorItemLength="+start + mShortIndicatorItemLength);
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mShortIndicatorItemLength, mPaint);
// start += mShortIndicatorItemLength + mIndicatorItemPadding;
// }
}
}
} else {
float partialLength = mShortIndicatorItemLength * progress;
for (int i = 0; i < pageCount; i++) {
if (nextPage > highlightPosition) {
if (i == highlightPosition) {
circlePaint.setColor(blendColor);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mLongIndicatorItemLength - partialLength, indicatorPosY, circlePaint);
start += itemWidth;
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mLongIndicatorItemLength - partialLength, mPaint);
// start += itemWidth;
// }
} else if (i == nextPage) {
circlePaint.setColor(blendColor1);
// if (canScrollHorizontally) {
c.drawLine(start - partialLength, indicatorPosY, start + mShortIndicatorItemLength, indicatorPosY, circlePaint);
start += mShortIndicatorItemLength + mIndicatorItemPadding;
// } else {
// c.drawLine(indicatorStartX, start - partialLength, indicatorStartX, start + mShortIndicatorItemLength, mPaint);
// start += mShortIndicatorItemLength + mIndicatorItemPadding;
// }
} else {
circlePaint.setColor(colorOff);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mShortIndicatorItemLength, indicatorPosY, circlePaint);
start += mShortIndicatorItemLength + mIndicatorItemPadding;
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mShortIndicatorItemLength, mPaint);
// start += mShortIndicatorItemLength + mIndicatorItemPadding;
// }
}
} else {
if (i == highlightPosition) {
circlePaint.setColor(blendColor);
// if (canScrollHorizontally) {
c.drawLine(start + partialLength, indicatorPosY, start + mLongIndicatorItemLength, indicatorPosY, circlePaint);
start += itemWidth;
// } else {
// c.drawLine(indicatorStartX, start + partialLength, indicatorStartX, start + mLongIndicatorItemLength, mPaint);
// start += itemWidth;
// }
} else if (i == nextPage) {
circlePaint.setColor(blendColor1);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mShortIndicatorItemLength + partialLength, indicatorPosY, circlePaint);
start += mShortIndicatorItemLength + mIndicatorItemPadding;
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mShortIndicatorItemLength + partialLength, mPaint);
// start += mShortIndicatorItemLength + mIndicatorItemPadding;
// }
} else {
circlePaint.setColor(colorOff);
// if (canScrollHorizontally) {
c.drawLine(start, indicatorPosY, start + mShortIndicatorItemLength, indicatorPosY, circlePaint);
start += mShortIndicatorItemLength + mIndicatorItemPadding;
// } else {
// c.drawLine(indicatorStartX, start, indicatorStartX, start + mShortIndicatorItemLength, mPaint);
// start += mShortIndicatorItemLength + mIndicatorItemPadding;
// }
}
}
}
}
}
}
这里面需要注意的几个地方protected final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
我想了解动画的朋友应该对插值器并不陌生, Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。而AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速。
具体可以去https://blog.csdn.net/qeqeqe236/article/details/32714835和https://blog.csdn.net/carson_ho/article/details/72863901研究一下
f = (layoutManager.getOffsetX() - currentPage * mRecyclerView.getWidth()) / (float) (mRecyclerView.getWidth());
progress=mInterpolator.getInterpolation(f);
layoutManager.getOffsetX() 列表的偏移量(起始绘制点)必须减去当前页面的列表宽度 因为有可能你滑动到第二页或者第三页这个偏移量会累加的。比如你的屏幕是1000px 那么当你滑动到第二页的时候你当前的偏移量就是1000px 滑动到第三页的时候是2000px。
而这个f 就是动画的速率 0为动画开始 1为结束 0-1之间的速率 后面可以根据这个速率计算出移动progress从而借助这个int blendColor = ColorUtils.blendARGB(colorOn, colorOff, progress);这个方法来根据速率开始时和结束时变换我们想要的颜色。
好了不知道你们看没看懂哈 反正我是记录一下!
网友评论