概要
做一个自动滑动的列表,用于展示聊天记录或者通知栏信息等,还是使用主流的RecyclerView来做。网上有很多案例,但当手动滑动时会一直无限循环,数据重复的出现,如果想要自动滑动时能无限循环,手动滑动时又能滑到底呢?本案例就解决这种手动滑动和自动滑动无缝斜街的问题。
思路
1、重写RecyclerView,通过scrollBy和postDelayed进行定时移动到达自动滑动目的
2、RecyclerView添加addOnScrollListener,进行手指按下滑动和抬起监听,用于判断是手动滑动还是自动滑动。
3、修改adapter的itemCount
4、接下来上代码
实现方案
1、重写 RecyclerView:
public class SocllRecyclerView extends RecyclerView {private Autoaaview autoview;private boolean running;private boolean canrun;private static final int Timea = 40;public SocllRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);autoview = new Autoaaview(this);}public SocllRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}private class Autoaaview implements Runnable{WeakReference<SocllRecyclerView> myScrViewWeakReference;public Autoaaview(SocllRecyclerView myScrView) {myScrViewWeakReference = new WeakReference<>(myScrView);}@Overridepublic void run() {SocllRecyclerView myScrView = myScrViewWeakReference.get();if (myScrView.canrun&&myScrView.running){myScrView.scrollBy(2,2);myScrView.postDelayed(myScrView.autoview,Timea);}}}public void stort(){if (running)stop();running = true;canrun = true;postDelayed(autoview,Timea);}public void stop() {running = false;removeCallbacks(autoview);}@Overridepublic boolean onTouchEvent(MotionEvent e) {return super.onTouchEvent(e);}
}
2、适配器 MyscrviewAdapter
public class MyscrviewAdapter extends RecyclerView.Adapter<ViewHolder> {Context context;List<NoticeBean.RecordsBean> mies;private int itemCount = Integer.MAX_VALUE;public MyscrviewAdapter(Context context, List<NoticeBean.RecordsBean> mies) {this.context = context;this.mies = mies;}public void updateAll(List<NoticeBean.RecordsBean> list) {mies.clear();mies.addAll(list);notifyDataSetChanged();}/*** 设置状态,用于设置ItemCount的数量* state:1 表示正在手指滑动,itemCount设置为实际数量;* 其他的表示结束手动滑动,itemCount设置为最大值Integer.MAX_VALUE* @param state*/public void setItemCount(int state) {this.itemCount = state == 1 ? mies.size() : Integer.MAX_VALUE;notifyDataSetChanged();}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View inflate = LayoutInflater.from(context).inflate(R.layout.item_home_news, parent, false);ViewHolder baseViewHolder = new ViewHolder(inflate);return baseViewHolder;}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, final int position) {holder.setText(R.id.tvNewsTitle, mies.get(position % mies.size()).getTitle());holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (null != mItemClickListener) {mItemClickListener.onItemClick(mies.get(position % mies.size()), position);}}});}@Overridepublic int getItemCount() {return mies.size() > 4 ? itemCount : mies.size();}//使用接口回调点击事件private ItemClickListener mItemClickListener;public void setOnItemClickListener(ItemClickListener itemClickListener) {this.mItemClickListener = itemClickListener;}
}
3、activity中使用
RecyclerView滑动监听,注释都说的很详细
/*** 控制通知公告数据滚动* 手指滑动时 停止自动滚动* 手指抬起时,3秒后自动开始滚动*/private void initRlvNews() {scroHandler = new Handler();//定义handlerrunnable = () -> { //runnable方法,处理延时后的操作newsAdapter.setItemCount(0);//0表示手指已经抬起来了rlvNews.stort(); //开始滑动};rlvNews.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {super.onScrollStateChanged(recyclerView, newState);if (null != newsAdapter) {if (newState == 1) {//newState的值:1 手指按下拖拽滚动,2自动滚动(一般指惯性滚动),0 禁止没有滚动rlvNews.stop();//停止自动滚动newsAdapter.setItemCount(newState);} else {scroHandler.removeCallbacks(runnable);//清除runnable重新开始//这里设置3秒是预估了手指滑动抬起再滑动的时间,提升体验scroHandler.postDelayed(runnable, 3000);}}}});}
4、布局文件:
需要给固定高度
<com.anyi.credit.bank.view.SocllRecyclerViewandroid:id="@+id/rlvNews"android:layout_width="match_parent"android:layout_height="144dp"/>
5、数据绑定
rlvNews.setLayoutManager()
MyscrviewAdapter adpter=new MyscrviewAdapter(this,list)
rlvNews.setAdapter(adpter)
//关键,条件自定义,如当列表数量大于4条时开始滑动
if(list.size()>4){
rlvNews.stort(); //开始滑动
}