美文网首页Android
RecyclerView双击返回顶部

RecyclerView双击返回顶部

作者: Maybe_G | 来源:发表于2018-04-27 10:30 被阅读1138次

    感谢 https://blog.csdn.net/My_Luna/article/details/50261925 Android之双击回到顶部
    感谢 https://www.jianshu.com/p/3acc395ae933 RecycleView4种定位滚动方式演示
    如果是操作ListView请直接看第一个链接里的内容

    0.先看效果

    TIM图片20180427103010.gif

    1.定义双击事件接口

    /** 
     * @author wfy 
     * 单击双击事件接口 
     */  
    public interface OnDoubleClickListener {  
        public void OnSingleClick(View v);  
            public void OnDoubleClick(View v);  
    } 
    

    2.定义DoubleClick类

    它提供一个静态方法给一个view注册双击事件,具体看注释
    /** 
     * @author wfy 
     * 消息列表+好友动态的双击回到顶部 
     */  
    public class DoubleClick {  
        public static void registerDoubleClickListener(View view, final OnDoubleClickListener listener){  
            if(listener==null) return;  
            view.setOnClickListener(new View.OnClickListener() {  
                //双击间隔时间350毫秒  
                private static final int DOUBLE_CLICK_TIME = 350;  
                private boolean flag = true;  
                private Handler handler = new Handler(){  
                    @Override  
                    public void handleMessage(Message msg) {  
                        listener.OnSingleClick((View)msg.obj);  
                    }  
                       
                };  
                //等待双击  
                public void onClick(final View v) {  
                    if(flag){  
                        flag = false;//与执行双击事件  
                        new Thread(){  
                            public void run() {  
                                try {  
                                    Thread.sleep(DOUBLE_CLICK_TIME);  
                                    //此时线程沉睡 而flag被修改为false  在DOUBLE_CLICK_TIME内点击则 进入else  
                                } catch (InterruptedException e) {  
                                    e.printStackTrace();  
                                }    //等待双击时间,否则执行单击事件  
                                if(!flag){  
                                    //睡醒了看一看flag被人动过没,没有人动,则认作单击事件  
                                    //因此不建议用此方法执行单击事件 因为会等待睡醒,有点击延迟的存在  
                                      
                                    //没有人动,自己把它改成true,以接受下次点击  
                                    flag = true;  
                                    Message msg = handler.obtainMessage();    
                                    msg.obj = v;  
                                    //发个消息,让执行单击  
                                    handler.sendMessage(msg);  
                                }  
                            }  
                               
                        }.start();  
                    }else{  
                        flag = true;  
                        listener.OnDoubleClick(v);    //执行双击  
                    }  
                }  
            });  
        }  
    }  
    

    3.给你要双击的组件注册双击事件

    此处以Button为例
    Button button=new Button(this);  
            DoubleClick.registerDoubleClickListener(button, new OnDoubleClickListener() {  
                  
                @Override  
                public void OnSingleClick(View v) {  
                    // TODO Auto-generated method stub  
                      
                }  
                  
                @Override  
                public void OnDoubleClick(View v) {  
                    // TODO Auto-generated method stub  
                    GoTopTask task=new GoTopTask();  
                    task.execute(firstposition);  
                }  
            });
    

    4.获取RecyclerView当前所在的item的position

    也就是给第3步中给firstposition赋值

    task.execute(firstposition);

    那么如何获得RecyclerView当前所在的item的position呢?

            //监听RecyclerView滚动位置firstPosition,并将firstPosition值传递给GoTopTask任务
            mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
                    if(lm instanceof LinearLayoutManager){
                        LinearLayoutManager linearManager = (LinearLayoutManager) lm;
                        //获取第一个可见view的位置
                        int firstItemPosition = linearManager.findFirstVisibleItemPosition();
                        firstPosition = firstItemPosition;
                    }
                }
            });
    

    5.GoTopTask异步任务

    最后要在这个任务中执行滚动的效果,但是RecyclerView有四种滚动效果(见文章开头链接),具体用哪一个需要考虑一下。
    • 如果当前item数量较少(也就是往下滑了很少内容)的话,可以直接使用RecyclerView的smoothScrollToPosition()方法,该方法自带滚动效果,可以从当前位置滚动到指定位置。
    • 如果当前item数量较多(也就是往下滑了好多内容)的话,那么使用以上方法就会把每个item都滚动完才能到顶部,肯定会消耗大量等待时间,影响用户体验。
    • RecyclerView的scrollToPosition()方法可以直接跳到指定位置。
    • 所以,当前item数量较多时,我们首先采用RecyclerView的scrollToPosition()方法先跳到指定位置(这里我设置了STARTPOSITION10,根据每条item条目内容高度,自己设定合理的值),然后再利用RecyclerView的smoothScrollToPosition()方法滚动到顶部,用户体验比较好。
    这是一个内部类
        /*===================新增====================*/
        /**
         * method desc.  : 传递当前RecyclerView的Item值,回滚到顶部
         *                 修改休眠值可以改变滚动时间
         * params        :
         * return        :
         */
        protected class GoTopTask extends AsyncTask<Integer, Integer, String> {
            private RecyclerView recyclerView;
            private static final int STARTPOSITION = 10;//开始滑动的位置
    
            public GoTopTask(View view) {
                recyclerView = (RecyclerView) view;
            }
    
            @Override
            protected void onPreExecute() {
                //回到顶部时间置0  此处的时间不是狭义上的时间
                super.onPreExecute();
            }
            @Override
            protected String doInBackground(Integer... params) {
                // TODO Auto-generated method stub
    
                for(int i=params[0];i>=0;i--){
    
                    //返回顶部时间耗费15个item还没回去,则直接去顶部
                    //目的:要产生滚动的假象,但也不能耗时过多
                    if(i > STARTPOSITION){
                        publishProgress(STARTPOSITION);
                        i = STARTPOSITION;
                    }else {
                        publishProgress(i);
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
            @Override
            public void onProgressUpdate(Integer... values) {
                //recyclerView.smoothScrollToPosition(values[0]);
                if(values[0] == STARTPOSITION){
                    recyclerView.scrollToPosition(values[0]);
                }else {
                    recyclerView.smoothScrollToPosition(values[0]);
                }
                super.onProgressUpdate(values);
            }
            @Override
            protected void onPostExecute(String result) {
                super.onPostExecute(result);
            }
            @Override
            protected void onCancelled() {
                // TODO Auto-generated method stub
                super.onCancelled();
            }
    
        }
    

    有问题留言。
    以上。

    相关文章

      网友评论

        本文标题:RecyclerView双击返回顶部

        本文链接:https://www.haomeiwen.com/subject/clfblftx.html