概要
做一个自动滑动的列表,用于展示聊天记录或者通知栏信息等,还是使用主流的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);
}
@Override
public void run() {
SocllRecyclerView myScrView = ();
if (&&){
(2,2);
(,Timea);
}
}
}
//开始滚动
public void start(){
if (running)
stop();
running = true;
canrun = true;
postDelayed(autoview,Timea);
}
//停止滚动
public void stop() {
running = false;
removeCallbacks(autoview);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
return (e);
}
}
2、适配器 MyscrviewAdapter
public class MyscrviewAdapter extends <ViewHolder> {
Context context;
List<> mies;
private int itemCount = Integer.MAX_VALUE;
public MyscrviewAdapter(Context context, List<> mies) {
= context;
= mies;
}
public void updateAll(List<> list) {
();
(list);
notifyDataSetChanged();
}
/**
* 设置状态,用于设置ItemCount的数量
* state:1 表示正在手指滑动,itemCount设置为实际数量;
* 其他的表示结束手动滑动,itemCount设置为最大值Integer.MAX_VALUE
* @param state
*/
public void setItemCount(int state) {
= state == 1 ? () : Integer.MAX_VALUE;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View inflate = (context).inflate(.item_home_news, parent, false);
ViewHolder baseViewHolder = new ViewHolder(inflate);
return baseViewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
(, (position % ()).getTitle());
(new () {
@Override
public void onClick(View v) {
if (null != mItemClickListener) {
((position % ()), position);
}
}
});
}
@Override
public int getItemCount() {
return () > 4 ? itemCount : ();
}
//使用接口回调点击事件
private ItemClickListener mItemClickListener;
public void setOnItemClickListener(ItemClickListener itemClickListener) {
= itemClickListener;
}
public interface ItemClickListener {
void onItemClick(Object obj, int position);
}
}
ViewHolder封装类
public class ViewHolder extends {
//用于缓存已找的界面
private SparseArray<View> mView;
public ViewHolder(View itemView) {
super(itemView);
mView=new SparseArray<>();
}
public <T extends View> T getView(int viewId){
//对已有的view做缓存
View view=(viewId);
//使用缓存的方式减少findViewById的次数
if(view==null){
view=(viewId);
(viewId,view);
}
return (T) view;
}
//通用的功能进行封装 设置文本 设置条目点击事件 设置图片
public ViewHolder setText(int viewId , CharSequence text){
TextView view = getView(viewId);
(text);
//希望可以链式调用
return this;
}
//通用的功能进行封装 设置文本 设置条目点击事件 设置图片
public ViewHolder setText(int viewId , String text){
TextView view = getView(viewId);
(text);
//希望可以链式调用
return this;
}
public ViewHolder setSelected(int viewId ,boolean selected){
TextView view = getView(viewId);
(selected);
//希望可以链式调用
return this;
}
public ViewHolder setSelected2(int viewId,boolean selected){
View view = getView(viewId);
(selected);
return this;
}
public ViewHolder setVisible(int viewId,boolean visible){
View view = getView(viewId);
(visible ? : );
return this;
}
public ViewHolder setVisible(int viewId,boolean visible,boolean isLocation){
View view = getView(viewId);
if (isLocation){
(visible ? : );
}else{
(visible ? : );
}
return this;
}
/**
*设置本地图片
* @param viewId
* @param resId
* @return
*/
public ViewHolder setImageResource(int viewId,int resId){
ImageView iv=getView(viewId);
(resId);
return this;
}
public ViewHolder setTextSelected(int viewId, boolean bool) {
TextView tv = getView(viewId);
(bool);
return this;
}
/**
*设置本地图片
* @param viewId
* @param resId
* @return
*/
public ViewHolder setImageDrawable(Context mContext, int viewId, int resId){
ImageView iv=getView(viewId);
(().getDrawable(resId));
return this;
}
/**
* 加载图片资源路径
* @param viewId
* @param imageLoader
* @return
*/
public ViewHolder setImagePath(int viewId,HolderImageLoader imageLoader,int res){
ImageView iv=getView(viewId);
(iv,(),res);
return this;
}
public ViewHolder setImage(Context mContext, int viewId, String url, int res) {
ImageView view = getView(viewId);
(mContext, view, url,res);
return this;
}
public ViewHolder setCircleImage(Context mContext, int viewId, String url, int res) {
ImageView view = getView(viewId);
(mContext, view, url,res);
return this;
}
public ViewHolder setTextColor(Context mContext, int viewId, int color) {
TextView tv = (TextView)(viewId);
(().getColor(color));
return this;
}
public ViewHolder setTextSize(Context mContext, int viewId, float res) {
TextView tv = (TextView)(viewId);
(Utils.dp2px(mContext,res));
return this;
}
@SuppressLint("NewApi")
public ViewHolder setBackground(Context mContext, int viewId, int bg) {
TextView tv = (TextView)(viewId);
(().getDrawable(bg));
return this;
}
/**
* 关于事件的
*/
public ViewHolder setOnClickListener(int viewId, listener) {
View view = getView(viewId);
(listener);
return this;
}
public abstract static class HolderImageLoader{
public String mPath;
public Context mContext;
public HolderImageLoader(Context mContext, String path){
=path;
= mContext;
}
/**
* 需要去复写这个方法加载图片
* @param iv
* @param path
*/
public abstract void loadImage(ImageView iv, String path, int res);
public String getPath(){
return mPath;
}
}
}
3、activity中使用
RecyclerView滑动监听,注释都说的很详细
/**
* 控制通知公告数据滚动
* 手指滑动时 停止自动滚动
* 手指抬起时,3秒后自动开始滚动
*/
private void initRlvNews() {
scroHandler = new Handler();//定义handler
runnable = () -> { //runnable方法,处理延时后的操作
(0);//0表示手指已经抬起来了
(); //开始滑动
};
(new () {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
(recyclerView, newState);
if (null != newsAdapter) {
if (newState == 1) {//newState的值:1 手指按下拖拽滚动,2自动滚动(一般指惯性滚动),0 禁止没有滚动
();//停止自动滚动
(newState);
} else {
(runnable);//清除runnable重新开始
//这里设置3秒是预估了手指滑动抬起再滑动的时间,提升体验
(runnable, 3000);
}
}
}
});
}
4、布局文件:
需要给固定高度
<
android:
android:layout_width="match_parent"
android:layout_height="144dp"/>
5、数据绑定
()//可设置水平滚动或竖直滚动布局
MyscrviewAdapter adpter=new MyscrviewAdapter(this,list)
(adpter)
//关键,条件自定义,如当列表数据大于4条时开始滑动
if(()>4){
(); //开始滑动
}