Android 自动滚动的RecyclerView,手动滑动和自动滑动无缝衔接,手动滑动时数据不重复

这篇具有很好参考价值的文章主要介绍了Android 自动滚动的RecyclerView,手动滑动和自动滑动无缝衔接,手动滑动时数据不重复。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概要

做一个自动滑动的列表,用于展示聊天记录或者通知栏信息等,还是使用主流的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 = myScrViewWeakReference.get();
            if (myScrView.canrun&&myScrView.running){
                myScrView.scrollBy(2,2);
                myScrView.postDelayed(myScrView.autoview,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 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
    @Override
    public 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;
    }

    @Override
    public 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() {
            @Override
            public void onClick(View v) {
                if (null != mItemClickListener) {
                    mItemClickListener.onItemClick(mies.get(position % mies.size()), position);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return mies.size() > 4 ? itemCount : mies.size();
    }

    //使用接口回调点击事件
    private ItemClickListener mItemClickListener;

    public void setOnItemClickListener(ItemClickListener itemClickListener) {
        this.mItemClickListener = itemClickListener;
    }
    
    public interface ItemClickListener {
        void onItemClick(Object obj, int position);
    }
}

ViewHolder封装类

public class ViewHolder extends RecyclerView.ViewHolder {
    //用于缓存已找的界面
    private SparseArray<View> mView;

    public ViewHolder(View itemView) {
        super(itemView);
        mView=new SparseArray<>();
    }
    public <T extends View> T getView(int viewId){
        //对已有的view做缓存
        View view=mView.get(viewId);
        //使用缓存的方式减少findViewById的次数
        if(view==null){
            view=itemView.findViewById(viewId);
            mView.put(viewId,view);
        }
        return (T) view;
    }
    //通用的功能进行封装  设置文本 设置条目点击事件  设置图片
    public ViewHolder setText(int viewId , CharSequence text){
        TextView view = getView(viewId);
        view.setText(text);
        //希望可以链式调用
        return this;
    }

    //通用的功能进行封装  设置文本 设置条目点击事件  设置图片
    public ViewHolder setText(int viewId , String text){
        TextView view = getView(viewId);
        view.setText(text);
        //希望可以链式调用
        return this;
    }

    public ViewHolder setSelected(int viewId ,boolean selected){
        TextView view = getView(viewId);
        view.setSelected(selected);
        //希望可以链式调用
        return this;
    }

    public ViewHolder setSelected2(int viewId,boolean selected){
        View view = getView(viewId);
        view.setSelected(selected);
        return this;
    }

    public ViewHolder setVisible(int viewId,boolean visible){
        View view = getView(viewId);
        view.setVisibility(visible ? View.VISIBLE : View.GONE);
        return this;
    }

    public ViewHolder setVisible(int viewId,boolean visible,boolean isLocation){
        View view = getView(viewId);
        if (isLocation){
            view.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
        }else{
            view.setVisibility(visible ? View.VISIBLE : View.GONE);
        }

        return this;
    }

    /**
     *设置本地图片
     * @param viewId
     * @param resId
     * @return
     */
    public ViewHolder setImageResource(int viewId,int resId){
        ImageView iv=getView(viewId);
        iv.setImageResource(resId);
        return this;
    }

    public ViewHolder setTextSelected(int viewId, boolean bool) {
        TextView tv = getView(viewId);
        tv.setSelected(bool);
        return this;
    }

    /**
     *设置本地图片
     * @param viewId
     * @param resId
     * @return
     */
    public ViewHolder setImageDrawable(Context mContext, int viewId, int resId){
        ImageView iv=getView(viewId);
        iv.setImageDrawable(mContext.getResources().getDrawable(resId));
        return this;
    }

    /**
     * 加载图片资源路径
     * @param viewId
     * @param imageLoader
     * @return
     */
    public ViewHolder setImagePath(int viewId,HolderImageLoader imageLoader,int res){
        ImageView iv=getView(viewId);
        imageLoader.loadImage(iv,imageLoader.getPath(),res);
        return this;
    }

    public ViewHolder setImage(Context mContext, int viewId, String url, int res) {
        ImageView view = getView(viewId);
        GlideLoadImageUtils.loadRectangleImg(mContext, view, url,res);
        return this;
    }

    public ViewHolder setCircleImage(Context mContext, int viewId, String url, int res) {
        ImageView view = getView(viewId);
        GlideLoadImageUtils.loadCircleImg(mContext, view, url,res);
        return this;
    }

    public ViewHolder setTextColor(Context mContext, int viewId, int color) {
        TextView tv = (TextView)this.getView(viewId);
        tv.setTextColor(mContext.getResources().getColor(color));
        return this;
    }

    public ViewHolder setTextSize(Context mContext, int viewId, float res) {
        TextView tv = (TextView)this.getView(viewId);
        tv.setTextSize(Utils.dp2px(mContext,res));
        return this;
    }

    @SuppressLint("NewApi")
    public ViewHolder setBackground(Context mContext, int viewId, int bg) {
        TextView tv = (TextView)this.getView(viewId);
        tv.setBackground(mContext.getResources().getDrawable(bg));
        return this;
    }

    /**
     * 关于事件的
     */
    public ViewHolder setOnClickListener(int viewId, View.OnClickListener listener) {
        View view = getView(viewId);
        view.setOnClickListener(listener);
        return this;
    }

    public abstract static class HolderImageLoader{
        public String mPath;
        public Context mContext;
        public HolderImageLoader(Context mContext, String path){
            this.mPath=path;
            this.mContext = 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方法,处理延时后的操作
            newsAdapter.setItemCount(0);//0表示手指已经抬起来了
            rlvNews.start(); //开始滑动
        };
        rlvNews.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public 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.SocllRecyclerView
 android: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.start(); //开始滑动

        }文章来源地址https://www.toymoban.com/news/detail-816609.html

结束------------

到了这里,关于Android 自动滚动的RecyclerView,手动滑动和自动滑动无缝衔接,手动滑动时数据不重复的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android:RecyclerView交互动画(上下拖动,左右滑动删除)

    @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //监听侧滑;1.删除数据,2.调用adapter.notifyItemRemoved(position) mMoveCallback.onItemRemove(viewHolder.getAdapterPosition()); } //改变选中的Item @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { //判断状态 if

    2024年04月12日
    浏览(29)
  • Android RecyclerView AsyncListUtil手动刷新fillData,kotlin

    Android RecyclerView AsyncListUtil手动刷新fillData,kotlin Android RecyclerView paging/pager/page implements based on AsyncListUtil,kotlin_zhangphil的博客-CSDN博客 基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见

    2024年02月13日
    浏览(25)
  • Android之解决RecyclerView与NestedScrollView的滑动冲突方法

    问题一:当我们滑动RecyclerView组件时,上方的轮播图并没有进行滑动(NestedScrollView没有滑动,即滑动事件被RecyclerView消费了), 当RecyclerView滑到底时,轮播图部分才进行滑动 。 如下图,RecyclerView已经进行了滑动,但轮播图部分没有。 整体布局 这并不符合我们的设计要求,

    2024年02月16日
    浏览(36)
  • 任务14、无缝衔接,MidJourney瓷砖(Tile)参数制作精良贴图

    在这个实验任务中,我们将深入探索《Midjourney Ai绘画》中的Tile技术和其在艺术创作中的具有挑战性的应用。此任务将通过理论学习与实践操作相结合的方式,让参与者更好地理解Tile的核心概念,熟练掌握如何在Midjourney平台上使用Tile参数,并实际运用到AI绘画的创作中。 首

    2024年02月14日
    浏览(29)
  • python与adb无缝衔接控制手机(手机截屏实例)

    目录 连接 常用操作 截图到PC端 使用pure-python-adb库可以实现python控制手机,支持input输入,支持shell命令,支持pull/push上传下载文件等。 安装库:pip install pure-python-adb 电脑端需要安装adb程序,在命令行窗口启动adb程序,如下: 连接 常用操作 截图到PC端

    2024年02月11日
    浏览(41)
  • 解决Android中使用RecyclerView滑动时底部item显示不全的问题

    感觉这个bug是不是因人而异啊,找了很多文章都没能解决我的问题,包括在RecyclerView上在嵌套上一层RelativeLayout,添加属性android:descendantFocusability=”blocksDescendants”,使用ConstraintLayout布局包裹RecyclerView,再设置layout_height=\\\"0dp\\\"和layout_constraintBottom_toBottomOf=\\\"parent\\\"(就是指定约束

    2024年02月16日
    浏览(34)
  • vue video 播完第一个视频以后,再无缝衔接第二个视频并循环播放

    这是一个项目中的实际需求,特此记录一下 页面中创建两个 video 标签 在组件加载时同时加载两个视频资源( autoplay ), 暂时不播放的视频在 canpl 了解规则 ay 事件中调用暂停方法,使之实现预加载 使用绝对定位将预加载的视频移出可视窗口 第一个视频结束后,通过 ended 事件

    2024年02月12日
    浏览(29)
  • Vue 之 vue-seamless-scroll 实现简单自动无缝滚动,且添加对应点击事件的简单整理

    目录 Vue 之 vue-seamless-scroll 实现简单自动无缝滚动,且添加对应点击事件的简单整理 一、简单介绍 二、安装和使用 三、效果图 四、vue-seamless-scroll 点击事件实现原理  五、简单实现  六、关键代码 Vue 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。 本

    2024年02月09日
    浏览(29)
  • [Unity学习]使用ScrollRect实现自动滚动到底部显示实时消息,并在拖动的时候取消自动滚动,再次手动滑到底部,又继续自动滚动

    首先需要重写ScrollRect组件: 下面通过协程实现在不滚动ScrollRect的时候,自动滚动到底部。 使用时,写下面类似代码即可: Unity原生Scroll View更改配置如下: 其中ScrollView游戏物体更改组件如下: content配置如下: 实现效果如下: 大功告成!加上对象池模式控制添加的text实例

    2024年02月16日
    浏览(23)
  • Cocos creator(2d) 使用 shader + uv 实现单张图片衔接滚动效果

    在游戏中,当我们需要让背景图片无缝衔接无限滚动时(打飞机这种背景一直滚动,或者肉鸽游戏地图一直在走等等),通常的做法是 在游戏中放两个背景node,在update中控制这两张背景图片的移动,并让其收尾衔接即可。(具体代码忽略) 可是在肉鸽类游戏中,玩家的走向是全方

    2024年02月13日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包