Android ListView 当前滚动位置 Y 像素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12727594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android ListView current scroll location Y pixels
提问by Juhani
I'm trying to detect when a list view is scrolled beyond certain fixed threshold in pixels (half way through the first item). Unfortunately listview's getScrollY() seems to always return 0 instad of the scroll position. Is there any way to get the actual scroll location by pixel?
我试图检测列表视图何时滚动超过以像素为单位的某个固定阈值(第一项的一半)。不幸的是,listview 的 getScrollY() 似乎总是返回滚动位置的 0 instad。有没有办法按像素获取实际滚动位置?
Here's the code I tried to use but as said it only returns 0.
这是我尝试使用的代码,但如上所述它只返回 0。
getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
Log.d("scroll", "scroll: " + getListView().getScrollY());
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == 0)
Log.d("scroll", "scrolling stopped");
}
});
回答by Cyril Mottier
There is no notion of Y scroll for a ListView in Android simply because the total height of the content is unknown. Only the height of the displayed content is known.
Android 中的 ListView 没有 Y 滚动的概念,因为内容的总高度是未知的。只有显示内容的高度是已知的。
However it is possible to get the current position/Y scroll of a visible item using the following hack:
但是,可以使用以下 hack 获取可见项目的当前位置/Y 滚动:
getListView().getChildAt(0).getTop();
回答by Tai Le Anh
A refactor code of Malachiasz's answer. This function is used for dynamic row's height.
Malachiasz 答案的重构代码。该函数用于动态行高。
Call onScroll listener
调用 onScroll 侦听器
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mCardsListView.getChildCount() > 0) {
int scrollY = getScrollY();
}
}
});
getScrollY function
getScrollY 函数
private Dictionary<Integer, Integer> mListViewItemHeights = new Hashtable<Integer, Integer>();
private int getScrollY() {
View child = mCardsListView.getChildAt(0); //this is the first visible row
if (child == null) return 0;
int scrollY = -child.getTop();
mListViewItemHeights.put(mCardsListView.getFirstVisiblePosition(), child.getHeight());
for (int i = 0; i < mCardsListView.getFirstVisiblePosition(); ++i) {
Integer hei = mListViewItemHeights.get(i);
//Manual add hei each row into scrollY
if (hei != null)
scrollY += hei;
}
return scrollY;
}
回答by Andrey Tuzov
Maybe it will be useful for someone. Code of previous answer's will not work when the list is scrolled fast. Because in this case firstVisiblePosition may be change irregular. In my code I do not use an array to store positions
也许它对某人有用。当列表快速滚动时,先前答案的代码将不起作用。因为在这种情况下 firstVisiblePosition 可能会发生不规则变化。在我的代码中,我不使用数组来存储位置
fun setOnTouchScrollListener(lv: AbsListView, onTouchScrollListener: (isDown: Boolean, offset: Int?, isScrollWorking: Boolean) -> Unit) {
var lastItemPosition: Int = -1
var lastItemTop: Int? = null
var lastItemHeight: Int? = null
var lastScrollState: Int? = AbsListView.OnScrollListener.SCROLL_STATE_IDLE
lv.setOnScrollListener(object : AbsListView.OnScrollListener {
override fun onScroll(view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int, totalItemCount: Int) {
val child = lv.getChildAt(0)
var offset: Int? = null
var isDown: Boolean? = if (firstVisibleItem == lastItemPosition || lastItemPosition == -1) null else firstVisibleItem > lastItemPosition
val dividerHeight = if (lv is ListView) lv.dividerHeight else 0
val columnCount = if (lv is GridView) lv.numColumns else 1
if (child != null) {
if (lastItemPosition != -1) {
when (firstVisibleItem - lastItemPosition) {
0 -> {
isDown = if (lastItemTop == child.top) null else lastItemTop!! > child.top
offset = Math.abs(lastItemTop!! - child.top)
}
columnCount -> offset = lastItemHeight!! + lastItemTop!! - child.top + dividerHeight
-columnCount -> offset = child.height + child.top - lastItemTop!! + dividerHeight
}
}
lastItemPosition = firstVisibleItem
lastItemHeight = child.height
lastItemTop = child.top
if (isDown != null && (offset == null || offset != 0)
&& lastScrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
onTouchScrollListener(isDown, offset, true)
}
}
}
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
lastScrollState = scrollState
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
onTouchScrollListener(true, 0, false)
lastItemPosition = -1
lastItemHeight = null
lastItemTop = null
}
}
})
}
Then we can use when a listview is scrolled beyond threshold
然后我们可以在列表视图滚动超过阈值时使用
private var lastThresholdOffset = 0
private var thresholdHeight = some value
setOnTouchScrollListener(listView) { isDown: Boolean, offset: Int?, isScrollWorking: Boolean ->
val offset = offset ?: if (isDown) 0 else thresholdHeight
lastThresholdOffset = if (isDown) Math.min(thresholdHeight, lastThresholdOffset + offset)
else Math.max(0, lastThresholdOffset - offset)
val result = lastThresholdOffset > thresholdHeight
}
isScrollWorking - can be used for animation
isScrollWorking - 可用于动画
回答by Rahul Ogale
You need two things to precisely define the scroll position of a listView:
您需要做两件事来精确定义 listView 的滚动位置:
To get current position:
获取当前位置:
int firstVisiblePosition = listView.getFirstVisiblePosition();
int topEdge=listView.getChildAt(0).getTop(); //This gives how much the top view has been scrolled.
To set the position:
要设置位置:
listView.setSelectionFromTop(firstVisiblePosition,0);
// Note the '-' sign...
listView.scrollTo(0,-topEdge);
回答by Lalit Poptani
You can try implementing OnTouchListener
and override its onTouch(View v, MotionEvent event)
and get the x and y using event.getX()
and event.getY()
. I had just created a demo for swipe on ListView row that will enable a delete button for deleting a particular item from the ListView. You can check the source code from my github as ListItemSwipe
.
您可以尝试实现OnTouchListener
并覆盖它onTouch(View v, MotionEvent event)
并使用event.getX()
and获取 x 和 y event.getY()
。我刚刚创建了一个用于在 ListView 行上滑动的演示,它将启用用于从 ListView 中删除特定项目的删除按钮。你可以从我的 github 中查看源代码作为ListItemSwipe
.