在项目中有这样需求要对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,可以根据具体环境进行调整。

最新文章

  1. SQL汉字转拼音函数-支持首字母、全拼
  2. (转)对比MS Test与NUnit Test框架
  3. 在Android平台下的基于Linux-C 的测试程序
  4. UI学习笔记---第一天
  5. POJ 1915
  6. 《分销系统-原创第一章》之“多用户角色权限访问模块问题”的解决思路( 位运算 + ActionFilterAttribute )
  7. (转)fastdfs group通过添加硬盘扩容
  8. Linus:为何对象引用计数必须是原子的
  9. Java泛型Restletclient
  10. Java中删除第一个集合中以某某开头的元素,删除第二个集合中以某某结尾的元素,并合并成一个集合
  11. python学习_1
  12. Selenium爬取电影网页写成csv文件
  13. 抢人就完事了——OO第二单元总结
  14. python爬虫之git的使用(github的使用)
  15. 疫情控制 [NOIP2012]
  16. Request获取客户端IP
  17. 张量系列(tensor02)
  18. python核心类库:urllib使用详解
  19. WorldWind源码剖析系列:数学引擎类MathEngine
  20. HDUOJ---老人是真饿了

热门文章

  1. emacs config on win10 for rust 1
  2. python spacy [E050] Can't find model 'en_core_web_sm'
  3. 【剑指Offer】【树】二叉搜索树的后序遍历序列
  4. C# 报表接口样例,简单实用
  5. Java面向对象之instanceof和类型转换
  6. Mac用自带软件QuickTime Player进行录屏
  7. awk 计算
  8. 081_Introducing trigger handler class
  9. filebeat+Elk实现日志收集并使用kibana展示
  10. Selinux讲解