利用RecyclerView實(shí)現(xiàn)無限循環(huán)滾動
一赤赊、先上效果圖
滾動
二、GitHub地址
GitHub地址 https://github.com/MNXP/AutomaticRolling
三疫萤、思路
RecycleView實(shí)現(xiàn)芝囤,內(nèi)部實(shí)現(xiàn)Runnable滾動
四次洼、實(shí)現(xiàn)
1)內(nèi)部實(shí)現(xiàn)Runnable
static class AutoPollTask implements Runnable {
private final WeakReference<AutoPollRecyclerView> mReference;
/**
* 使用弱引用持有外部類引用,防止內(nèi)存泄漏
*/
private AutoPollTask(AutoPollRecyclerView reference) {
this.mReference = new WeakReference<>(reference);
}
@Override
public void run() {
AutoPollRecyclerView recyclerView = mReference.get();
if (recyclerView != null && recyclerView.running) {
recyclerView.scrollBy(2, 2);//每次滾動距離
/**
* 判斷是否為無限循環(huán)
*/
if (recyclerView.canRun){
/**
* 判斷是否觸底
*/
if (isSlideToBottom(recyclerView)) {
/**跳至頂部*/
recyclerView.smoothScrollToPosition(0);
}
}
recyclerView.postDelayed(recyclerView.autoPollTask,TIME_AUTO_POLL);
}
}
}
/**判斷Recycler是否滑動至最底部 是返回true 不是返回false*/
public static boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) return false;
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
>= recyclerView.computeVerticalScrollRange())
return true;
return false;
}
2)開啟滾動
//開啟
public void start() {
if (running){
return;
}
canRun = true;
running = true;
postDelayed(autoPollTask,TIME_AUTO_POLL);
}
public void setCanRun(boolean canRun){
this.canRun = canRun;
}
3)設(shè)置最大高度(沒用到可以去掉)
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int heightMode = MeasureSpec.getMode(heightSpec);
int heightSize = MeasureSpec.getSize(heightSpec);
if (heightMode == MeasureSpec.EXACTLY) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
if (heightMode == MeasureSpec.UNSPECIFIED) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
heightMode);
super.onMeasure(widthSpec, maxHeightMeasureSpec);
}
4)自身Adapter設(shè)置
@Override
public int getItemCount() {
if (mData!=null){
if (mData.size()<=3)
return mData.size();
else
return mData.size()*20;//return Integer.MAX_VALUE;
}else {
return 0;
}
}
5)引用
autoPollRecyclerView = (AutoPollRecyclerView) itemView.findViewById(R.id.main_recycler);
autoPollRecyclerView.start();
autoPollRecyclerView.setNestedScrollingEnabled(false);
autoPollRecyclerView.setLayoutManager(new LinearLayoutManager(context,LinearLayoutManager.VERTICAL, false));
((SimpleItemAnimator) autoPollRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
/**
* 我的是超過3項(xiàng)開始滾動
*/
if (item.list.size() > 0) {
if (item.list.size() <= 3) {
viewHolder.autoPollRecyclerView.setCanRun(false);
} else {
viewHolder.autoPollRecyclerView.setCanRun(true);
}
}
6)自動滾動RecycleView完整代碼
public class AutoPollRecyclerView extends RecyclerView {
private static final long TIME_AUTO_POLL = 30;
private AutoPollTask autoPollTask;
private boolean running; //是否正在自動輪詢
private boolean canRun;//是否可以自動輪詢,可在不需要的是否置false
private int mMaxHeight;//最大高度
public AutoPollRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
autoPollTask = new AutoPollTask(this);
mMaxHeight = dip2px(context,100);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return false;
}
static class AutoPollTask implements Runnable {
private final WeakReference<AutoPollRecyclerView> mReference;
/**
* 使用弱引用持有外部類引用,防止內(nèi)存泄漏
*/
private AutoPollTask(AutoPollRecyclerView reference) {
this.mReference = new WeakReference<>(reference);
}
@Override
public void run() {
AutoPollRecyclerView recyclerView = mReference.get();
if (recyclerView != null && recyclerView.running) {
recyclerView.scrollBy(2, 2);//每次滾動距離
/**
* 判斷是否為無限循環(huán)
*/
if (recyclerView.canRun){
/**
* 判斷是否觸底
*/
if (isSlideToBottom(recyclerView)) {
/**跳至頂部*/
recyclerView.smoothScrollToPosition(0);
}
}
recyclerView.postDelayed(recyclerView.autoPollTask,TIME_AUTO_POLL);
}
}
}
/**判斷Recycler是否滑動至最底部 是返回true 不是返回false*/
public static boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) return false;
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
>= recyclerView.computeVerticalScrollRange())
return true;
return false;
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int heightMode = MeasureSpec.getMode(heightSpec);
int heightSize = MeasureSpec.getSize(heightSpec);
if (heightMode == MeasureSpec.EXACTLY) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
if (heightMode == MeasureSpec.UNSPECIFIED) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = heightSize <= mMaxHeight ? heightSize
: (int) mMaxHeight;
}
int maxHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
heightMode);
super.onMeasure(widthSpec, maxHeightMeasureSpec);
}
//開啟
public void start() {
if (running){
return;
}
canRun = true;
running = true;
postDelayed(autoPollTask,TIME_AUTO_POLL);
}
public void setCanRun(boolean canRun){
this.canRun = canRun;
}
/**
* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)
*/
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
7)小小的建議
RecycleView實(shí)現(xiàn)关贵,首頁列表,加載圖片有卡頓
卡頓優(yōu)化可以使用vLayout(阿里開源庫)處理挺好的滓玖,它只要是用于處理列表不同布局
vLayout地址 (https://github.com/alibaba/vlayout)
如有意見和建議坪哄,及時溝通。