zoukankan      html  css  js  c++  java
  • ListView,ScrollView,RecyclerView上下滑动监听


    在项目中有这样需求要对ListView或ScrollView或RecyclerView滚动进行监听,来做一些处理,下面来看对应实现

    一:Listview上下滑动监听

    通过实现AbsListView.OnScrollListener接口onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)实现(通过判断firstItem与前一次的差值比较)

    下面是对接口封装处理

    abstract class AbsListViewScrollDetector implements AbsListView.OnScrollListener {
        private int mLastScrollY;
        private int mPreviousFirstVisibleItem;
        private AbsListView mListView;
        private int mScrollThreshold;
    
        abstract void onScrollUp();
    
        abstract void onScrollDown();
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if(totalItemCount == 0) return;
            if (isSameRow(firstVisibleItem)) {
                int newScrollY = getTopItemScrollY();
                boolean isSignificantDelta = Math.abs(mLastScrollY - newScrollY) > mScrollThreshold;
                if (isSignificantDelta) {
                    if (mLastScrollY > newScrollY) {
                        onScrollUp();
                    } else {
                        onScrollDown();
                    }
                }
                mLastScrollY = newScrollY;
            } else {
                if (firstVisibleItem > mPreviousFirstVisibleItem) {
                    onScrollUp();
                } else {
                    onScrollDown();
                }
    
                mLastScrollY = getTopItemScrollY();
                mPreviousFirstVisibleItem = firstVisibleItem;
            }
        }
    
        public void setScrollThreshold(int scrollThreshold) {
            mScrollThreshold = scrollThreshold;
        }
    
        public void setListView(AbsListView listView) {
            mListView = listView;
        }
    
        private boolean isSameRow(int firstVisibleItem) {
            return firstVisibleItem == mPreviousFirstVisibleItem;
        }
    
        private int getTopItemScrollY() {
            if (mListView == null || mListView.getChildAt(0) == null) return 0;
            View topChild = mListView.getChildAt(0);
            return topChild.getTop();
        }
    }


    这里分为两种情况处理:

    1,比较两次firstItem差值进行判断 ,这种情况比较容易考虑到,还有另外一种情况2

    2,如果当滑动距离较小时(或者itemView高度较大)为一个ItemView,需要判断Itemview距离顶部距离判断进行比较处理


    二:ScrollView滚动上下滚动监听


    ScrollView并没有提供像ListViewt那样监听器,那如何实现呢?答案就是继承ScrollView 重新onScrollChanged方法判断,并提供监听回调

    具体实现:

    public class ObservableScrollView extends ScrollView {
    
        public interface OnScrollChangedListener {
            void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt);
        }
    
        private OnScrollChangedListener mOnScrollChangedListener;
    
        public ObservableScrollView(Context context) {
            super(context);
        }
    
        public ObservableScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            if (mOnScrollChangedListener != null) {
                mOnScrollChangedListener.onScrollChanged(this, l, t, oldl, oldt);
            }
        }
    
        public void setOnScrollChangedListener(OnScrollChangedListener listener) {
            mOnScrollChangedListener = listener;
        }
    }

    即当我们使用ScollView时,使用ObservableScrollView替换即可,这里需要注意的是onScrollChanged方法并不是ScrollView独有定义的,SrollView继承FrameLayout

    FrameLayout继承ViewGroup,也不在ViewGroup,FrameLayout,而是来源于View基类,源码说明如下:

    /**
         * This is called in response to an internal scroll in this view (i.e., the
         * view scrolled its own contents). This is typically as a result of
         * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
         * called.
         *
         * @param l Current horizontal scroll origin.
         * @param t Current vertical scroll origin.
         * @param oldl Previous horizontal scroll origin.
         * @param oldt Previous vertical scroll origin.
         */
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
                postSendViewScrolledAccessibilityEventCallback();
            }
    
            mBackgroundSizeChanged = true;
    
            final AttachInfo ai = mAttachInfo;
            if (ai != null) {
                ai.mViewScrollChanged = true;
            }
    
            if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
                mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
            }
        }

    即当调用SrollBy(),或ScrollTo()是调用,而ScrollView内部就是调用这两方法,所有可以通过重写此方法实现


    下面实现是监听实现:

    abstract class ScrollViewScrollDetector implements ObservableScrollView.OnScrollChangedListener {
        private int mLastScrollY;
        private int mScrollThreshold;
    
        abstract void onScrollUp();
    
        abstract void onScrollDown();
    
        @Override
        public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
            boolean isSignificantDelta = Math.abs(t - mLastScrollY) > mScrollThreshold;
            if (isSignificantDelta) {
                if (t > mLastScrollY) {
                    onScrollUp();
                } else {
                    onScrollDown();
                }
            }
            mLastScrollY = t;
        }
    
        public void setScrollThreshold(int scrollThreshold) {
            mScrollThreshold = scrollThreshold;
        }
    }


    三:RecyclerView实现滚动方向判断

    比较简单,因为系统以提供对应接口RecyclerView.OnScrollListener ,滚动dx,dy已给出

    实现如下:

    abstract class RecyclerViewScrollDetector extends RecyclerView.OnScrollListener {
        private int mScrollThreshold;
    
        abstract void onScrollUp();
    
        abstract void onScrollDown();
    
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            boolean isSignificantDelta = Math.abs(dy) > mScrollThreshold;
            if (isSignificantDelta) {
                if (dy > 0) {
                    onScrollUp();
                } else {
                    onScrollDown();
                }
            }
        }
    
        public void setScrollThreshold(int scrollThreshold) {
            mScrollThreshold = scrollThreshold;
        }
    }

    说明,mScrollThreshold的大小这里设置4dp,可以根据具体环境进行调整。

  • 相关阅读:
    Salesforce的数据权限机制
    Java并发编程:Java内存模型和volatile
    Java并发编程:synchronized和锁优化
    权限控制和OAuth
    MySQL explain详解
    ConcurrentHashMap源码阅读
    HashMap源码阅读
    领域驱动设计的基础知识总结
    Chris Richardson微服务翻译:重构单体服务为微服务
    Chris Richardson微服务翻译:微服务部署
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6150740.html
Copyright © 2011-2022 走看看