描述:这是一个基于recyclerview实现的 Android 无限循环滚动Demo,可自定义item。
项目代码在最后面!!!!跳转到最后 控件效果如下:此控件为Android 无限循环居中并可以自动向下滚动。
- 上下滚动无限循环(跳转回之前相似的postion)
- 自动滚动
- 利用flex可进行流式内容布局
主要的设计核心是依赖于recyclerview进行设计的,主要通过重写layoutmanager,Adapter,RecyclerView等来实现
核心代码:CycleFlexManager .java
根据数量进行高度调整
package com.ui.design.view.automeasurelinear.linearmanager;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.flexbox.FlexboxLayoutManager;
public class CycleFlexManager extends FlexboxLayoutManager {
private RecyclerView mRecyclerView;
private int mItemViewHeight = 0;
public CycleFlexManager(Context context, RecyclerView recyclerView) {
super(context);
this.mRecyclerView = recyclerView;
}
public CycleFlexManager(Context context, int flexDirection) {
super(context, flexDirection);
}
public CycleFlexManager(Context context, int flexDirection, int flexWrap) {
super(context, flexDirection, flexWrap);
}
public CycleFlexManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void onAttachedToWindow(RecyclerView view) {
super.onAttachedToWindow(view);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == 0) {
int topposition = findFirstVisibleItemPosition();
int lastpostion = findLastCompletelyVisibleItemPosition();
Log.e("TEST", "findFirstVisibleItemPosition" + topposition);
Log.e("TEST", "findLastVisibleItemPosition" + lastpostion);
if (lastpostion > getItemCount() - 5) {//有些View可能转载比较多item 用顶部的postion来指示
int prepostion = lastpostion - getItemCount() / 2;
Log.e("TEST", "childconut" + prepostion);
// View view=findViewByPosition(lastpostion);
scrollToPosition(prepostion + 1); //找到可视图里第一个postion并让他向前移动一半
}
if (topposition == 0) {
int prepostion = topposition + getItemCount() / 2;
Log.e("TEST", "childconut" + prepostion);
scrollToPosition(prepostion-1);
}
}
}
public int getmItemViewHeight() {
if (mItemViewHeight==0){
View view=findViewByPosition(0);
if (view!=null){
measureChildWithMargins(view, 0, 0);
mItemViewHeight = view.getMeasuredHeight();
}
}
return mItemViewHeight;
}
}
AutoPollRecyclerView .java
自动滚动
package com.ui.design.view.automeasurelinear.recyclerview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.ui.design.view.automeasurelinear.linearmanager.CycleFlexManager;
import java.lang.ref.WeakReference;
public class AutoPollRecyclerView extends RecyclerView {
private static final long TIME_AUTO_POLL = 16;
AutoPollTask autoPollTask;
private boolean running; //表示是否正在自动轮询
private boolean canRun;//表示是否可以自动轮询
public AutoPollRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
autoPollTask = new AutoPollTask(this);
}
static class AutoPollTask implements Runnable {
private final WeakReference mReference;
//使用弱引用持有外部类引用->防止内存泄漏
public AutoPollTask(AutoPollRecyclerView reference) {
this.mReference = new WeakReference<>(reference);
}
@Override
public void run() {
AutoPollRecyclerView recyclerView = mReference.get();
if (recyclerView.running && recyclerView.canRun) {
recyclerView.scrollBy(2, 2);
if (!recyclerView.canScrollVertically(5)){
if (recyclerView.getLayoutManager() instanceof CycleFlexManager){
((CycleFlexManager)recyclerView.getLayoutManager()).onScrollStateChanged(0);//向无限循环manager释放不滚动信号 进行位置迁移
}
}
recyclerView.postDelayed(recyclerView.autoPollTask, TIME_AUTO_POLL);
}
}
}
//开启:如果正在运行,先停止->再开启
public void start() {
if (running)
stop();
canRun = true;
running = true;
postDelayed(autoPollTask, TIME_AUTO_POLL);
}
public void stop() {
running = false;
removeCallbacks(autoPollTask);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
if (running)
stop();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
if (canRun)
start();
break;
}
return super.onTouchEvent(e);
}
private int cycleNum=4;
public int getCycleNum() {
return cycleNum;
}
public void setCycleNum(int cycleNum) {
this.cycleNum = cycleNum;
}
}
AutoMeasureAdapter.java 在Adapter中将size增加 不然无法实现无限循环滚动
package com.ui.design.view.automeasurelinear.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.alibaba.android.arouter.launcher.ARouter; import com.ui.design.R; import com.ui.design.main.bean.SelectorBean; import com.ui.design.view.pickviewselect.view.PickerLayoutManager; import java.util.List; public class AutoMeasureAdapter extends RecyclerView.Adapter使用示例:{ private final List mList; private final Context mContext; private int mCycleNum=8;//长度重复次数 默认为8 public AutoMeasureAdapter(Context context, List stringList){ this.mContext=context; this.mList=stringList; } @NonNull @Override public SViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new SViewHolder(LayoutInflater.from(mContext).inflate(R.layout.automeasure_adapter_item, parent,false)); } @Override public void onBindViewHolder(@NonNull SViewHolder holder, int position) { if (mList == null || mList.size() == 0) { return; } holder.cardname.setText(mList.get(position % mList.size())); } @Override public int getItemCount() { if (mList == null||mList.size()==0) { return 0; } return mList.size() * mCycleNum;//直接乘 } static class SViewHolder extends RecyclerView.ViewHolder{ private final TextView cardname; public SViewHolder(@NonNull View itemView) { super(itemView); cardname=(TextView) itemView.findViewById(R.id.card_name); } } public int getmCycleNum() { return mCycleNum; } public void setmCycleNum(int mCycleNum) { if (mCycleNum%2==1){ mCycleNum++;//保证mCycleNum为2的倍数 } this.mCycleNum = mCycleNum; } }
AutomeasureActivity.java
package com.ui.design.view.automeasurelinear;
import androidx.recyclerview.widget.RecyclerView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.JustifyContent;
import com.ui.design.R;
import com.ui.design.main.base.baseActivity;
import com.ui.design.main.constants.Constants;
import com.ui.design.utils.RandomValue;
import com.ui.design.view.automeasurelinear.adapter.AutoMeasureAdapter;
import com.ui.design.view.automeasurelinear.linearmanager.CycleFlexManager;
import com.ui.design.view.automeasurelinear.recyclerview.AutoPollRecyclerView;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@Route(path = Constants.AutomeasureActivity)
public class AutomeasureActivity extends baseActivity {
private List stringList;
@Override
protected int initLayout() {
return R.layout.activity_automeasure;
}
@Override
protected void initView() {
stringList=new ArrayList<>();
for (int i=0;i<50;i++){
stringList.add(RandomValue.getRandomContent());
}
AutoPollRecyclerView recyclerView=findViewById(R.id.auto_center);
CycleFlexManager layoutManager = new CycleFlexManager(this,recyclerView);
layoutManager.setFlexDirection(FlexDirection.ROW);//可设置排列
layoutManager.setJustifyContent(JustifyContent.CENTER);//可设置是否居中
recyclerView.setLayoutManager(layoutManager);
recyclerView.start();
AutoMeasureAdapter autoMeasureAdapter = new AutoMeasureAdapter(this,stringList);
recyclerView.setAdapter(autoMeasureAdapter);
}
@Override
protected void initData() {
}
}
activity_automeasure.xml
项目代码仓库
如果直接复制可能会出现代码缺陷,完整代码请去仓库下载
如果觉得还行,耽误您几秒钟的时间去我的仓库点点star,万一以后用到了呢?



