首先單個(gè)我們知道recyclerview翻頁(yè)效果一般是配合viewPager來(lái)完成的 但是如何做到單個(gè)fragment無(wú)需viewPager也能完成操作呢!
這個(gè)時(shí)候就需要谷歌的官方推薦的SnapHelper 來(lái)完成這個(gè)需求 但是又有大神幫忙封裝好了就直接拿來(lái)用就好哈哈
導(dǎo)入sdk implementation 'com.gcssloop.support:pagerlayoutmanager:1.3.1@aar'
LogUtils.i(TAG,"servicefragment 列表展示 數(shù)據(jù)大性侣濉:"+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)細(xì)節(jié) 如果是整數(shù)不會(huì)向上取整
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) 這個(gè)方法 必須設(shè)置為null 查看源碼后發(fā)現(xiàn)有的時(shí)候會(huì)找不到recyclerview實(shí)例 導(dǎo)致崩潰的問(wèn)題
下面是自定義指示器的代碼 有點(diǎn)亂哈 沒(méi)有優(yōu)化的版本
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;
}
//計(jì)算 指示器長(zhǎng)和短的長(zhǎng)度和
float totalLength = mLongIndicatorItemLength + mShortIndicatorItemLength * (pageNum - 1);
//計(jì)算指示器外邊距總距離
float paddingBetweenItems = Math.max(0, pageNum - 1) * mIndicatorItemPadding;
//指示器真正的長(zhǎng)度
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);
//需要獲取當(dāng)前頁(yè) 參數(shù)
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;
// }
}
}
}
}
}
}
這里面需要注意的幾個(gè)地方protected final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
我想了解動(dòng)畫的朋友應(yīng)該對(duì)插值器并不陌生, Interpolator 被用來(lái)修飾動(dòng)畫效果,定義動(dòng)畫的變化率撵术,可以使存在的動(dòng)畫效果accelerated(加速),decelerated(減速),repeated(重復(fù)),bounced(彈跳)等话瞧。而AccelerateDecelerateInterpolator 在動(dòng)畫開始與結(jié)束的地方速率改變比較慢嫩与,在中間的時(shí)候加速。
具體可以去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() 列表的偏移量(起始繪制點(diǎn))必須減去當(dāng)前頁(yè)面的列表寬度 因?yàn)橛锌赡苣慊瑒?dòng)到第二頁(yè)或者第三頁(yè)這個(gè)偏移量會(huì)累加的交排。比如你的屏幕是1000px 那么當(dāng)你滑動(dòng)到第二頁(yè)的時(shí)候你當(dāng)前的偏移量就是1000px 滑動(dòng)到第三頁(yè)的時(shí)候是2000px划滋。
而這個(gè)f 就是動(dòng)畫的速率 0為動(dòng)畫開始 1為結(jié)束 0-1之間的速率 后面可以根據(jù)這個(gè)速率計(jì)算出移動(dòng)progress從而借助這個(gè)int blendColor = ColorUtils.blendARGB(colorOn, colorOff, progress);這個(gè)方法來(lái)根據(jù)速率開始時(shí)和結(jié)束時(shí)變換我們想要的顏色。
好了不知道你們看沒(méi)看懂哈 反正我是記錄一下埃篓!