【发布时间】:2012-03-26 15:45:55
【问题描述】:
有没有办法识别列表视图是向上滚动还是向下滚动?
OnScrollListener 在这种情况下对我没有帮助。
提前致谢!
【问题讨论】:
-
您到底想要什么?你能解释更多吗...
-
我想在列表向上滚动时编写一些代码,并在列表向下滚动时编写其他代码。因此,我想检测它是向上还是向下滚动
有没有办法识别列表视图是向上滚动还是向下滚动?
OnScrollListener 在这种情况下对我没有帮助。
提前致谢!
【问题讨论】:
这是一个简单的实现:
lv.setOnScrollListener(new OnScrollListener() {
private int mLastFirstVisibleItem;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState){}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(mLastFirstVisibleItem < firstVisibleItem){
// Scrolling down
}
if(mLastFirstVisibleItem > firstVisibleItem){
// scrolling up
}
mLastFirstVisibleItem = firstVisibleItem;
}
});
【讨论】:
ScrollViews 中有一个方法可以报告卷轴的移动。它被称为onScrollChanged()。但是,它被声明为受保护,因此您必须创建一个包装类来获得访问权限。该方法的使用方法请查看android docs。
首先,创建一个接口来暴露受保护的方法
public interface OnScrollListener {
void onScrollChanged(int x, int y, int oldx, int oldy);
}
然后,创建你的包装器并扩展 ScrollView
public class ReportingScrollView extends ScrollView {
private OnScrollListener onScrollListener = null;
public ReportingScrollView(Context context) {
super(context);
}
public ReportingScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ReportingScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (onScrollListener != null) {
onScrollListener.onScrollChanged(x, y, oldx, oldy);
}
}
}
最后,像自定义视图一样将它包含在您的 XML 布局中,并像往常一样附加侦听器。
<your.package.ReportingScrollView />
scrollingandtrolling.setOnScrollListener(new OnScrollListener() {...});
【讨论】:
对于那些还在为 kotlin 寻找答案的人来说,这适用于它
MainListView.setOnScrollListener(object :AbsListView.OnScrollListener {
// var VisibleItem: Int = 0
override fun onScroll(p0: AbsListView?, FirstVisibleItem: Int, i2: Int, i3: Int) {
/*
if(VisibleItem < FirstVisibleItem)
{
Toast.makeText(applicationContext,"Scrolling Down",Toast.LENGTH_SHORT).show()
fab.hide()
}
if(VisibleItem >FirstVisibleItem)
{
fab.show()
Toast.makeText(applicationContext,"Scrolling Up",Toast.LENGTH_SHORT).show()
}
VisibleItem=FirstVisibleItem;
*/
}
override fun onScrollStateChanged(p0: AbsListView?, p1: Int) {
if (p1 == 1) {
fab.hide()
} else {
fab.show()
}
}
})
}
取消注释以使用替代方法。
【讨论】:
一个简单而有效的解决方案。
private int lastPosition = -1;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
if(lastPosition == firstVisibleItem)
{
return;
}
if(firstVisibleItem > lastPosition)
{
Logger.print("Going Down");
}
else
{
Logger.print("Going Up");
}
lastPosition = firstVisibleItem;
}
【讨论】:
Some Noob Student 给出的解决方案很好:您必须创建一个包装器才能使用受保护的 onScrollChanged(int x, int y, int oldx, int oldy) 方法,该方法比标准 AbsListView.OnScrollListener 更频繁地触发.onScrollStateChanged(AbsListView view, int scrollState).
不幸的是,无论我如何滚动,onScrollChanged() 始终返回 0 作为参数,并且似乎仅在滚动结束时才检测到,到达列表的顶部或底部。
所以我使用下面的代码来检测滚动的正确方向:它使用第一个可见项目的 getTop(),但也使用它的位置来了解第一个项目何时不再可见;在此项目转换期间,滚动方向由项目位置本身给出。
@Override
public void onScrollChanged(int x, int y, int oldx, int oldy) {
if(listView.getChildAt(0) != null) {
int scrollingDir = NO_SCROLLING;
int firstChildTop = listView.getChildAt(0).getTop();
if (listView.getFirstVisiblePosition() == mLastFirstVisiblePosition) {
if (mLastFirstChildTop < firstChildTop) {
//Scrolling DOWN
scrollingDir = SCROLLING_DOWN;
} else if (mLastFirstChildTop > firstChildTop) {
//Scrolling UP
scrollingDir = SCROLLING_UP;
}
} else if(listView.getFirstVisiblePosition() > mLastFirstVisiblePosition) {
//Scrolling UP
scrollingDir = SCROLLING_UP;
} else {
//Scrolling DOWN
scrollingDir = SCROLLING_DOWN;
}
mLastFirstVisiblePosition = listView.getFirstVisiblePosition();
mLastFirstChildTop = firstChildTop;
switch(scrollingDir) {
case SCROLLING_DOWN:
//Your DOWN scrolling code here
break;
case SCROLLING_UP:
//Your UP scrolling code here
break;
default:
case NO_SCROLLING:
break;
}
}
}
【讨论】:
list.setOnScrollListener(new OnScrollListener() {
int last_item;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(last_item<firstVisibleItem+visibleItemCount-1){
System.out.println("List is scrolling upwards");
}
else if(last_item>firstVisibleItem+visibleItemCount-1){
System.out.println("List is scrolling downwards");
}
last_item = firstVisibleItem+visibleItemCount-1;
}
});
这里根据最后一个可见项目,我决定列表是上升还是下降
【讨论】: