我有一個listView。當我滾動並停在某個特定的地方時。Android listView找到滾動的像素量
如何獲得我滾動的像素數量(從頂部)?
我一直在使用得到listView.getScrollY()試過了,但它返回0。
我有一個listView。當我滾動並停在某個特定的地方時。Android listView找到滾動的像素量
如何獲得我滾動的像素數量(從頂部)?
我一直在使用得到listView.getScrollY()試過了,但它返回0。
我有同樣的問題。
我不能使用View.getScrollY(),因爲它總是返回0,我不能使用OnScrollListener.onScroll(...),因爲它適用於不與像素相關的位置。我不能繼承ListView並覆蓋onScrollChanged(...),因爲它的參數值始終是0. Meh。
所有我想知道的是孩子(即listview的內容)滾動上下的數量。所以我想出了一個解決方案。我跟蹤其中一個孩子(或者你可以說其中一個「行」),並按照其垂直位置變化。
下面是代碼:
public class ObservableListView extends ListView {
public static interface ListViewObserver {
public void onScroll(float deltaY);
}
private ListViewObserver mObserver;
private View mTrackedChild;
private int mTrackedChildPrevPosition;
private int mTrackedChildPrevTop;
public ObservableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (mTrackedChild == null) {
if (getChildCount() > 0) {
mTrackedChild = getChildInTheMiddle();
mTrackedChildPrevTop = mTrackedChild.getTop();
mTrackedChildPrevPosition = getPositionForView(mTrackedChild);
}
} else {
boolean childIsSafeToTrack = mTrackedChild.getParent() == this && getPositionForView(mTrackedChild) == mTrackedChildPrevPosition;
if (childIsSafeToTrack) {
int top = mTrackedChild.getTop();
if (mObserver != null) {
float deltaY = top - mTrackedChildPrevTop;
mObserver.onScroll(deltaY);
}
mTrackedChildPrevTop = top;
} else {
mTrackedChild = null;
}
}
}
private View getChildInTheMiddle() {
return getChildAt(getChildCount()/2);
}
public void setObserver(ListViewObserver observer) {
mObserver = observer;
}
}
夫婦的注意事項:
如果添加速度計算(例如,delta_pos/delta_time),請記住當滾動停止時視圖停止調用onScrollChanged,因此在最後一次滾動調用和下一次滾動的第一次調用之間可能會有很長時間;只是忽略(delta_time <100)或者其他一些。 – cdhabecker
我用自己的方式,但最初它給我0值,你能告訴我爲什麼會這樣,我使用PullToRefresh也讓您可以指導我 –
當在列表視圖初始化'onScroll'監聽器將被調用,它不使用的觸摸 – Ninja
嘗試實施OnScrollListener:
list.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int last = view.getLastVisiblePosition();
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
你不能得到名列榜首像素(因爲那時你需要從列表頂部佈局所有視圖 - 可能有很多項目)。但你可以得到第一個可見項的像素:int pixels = listView.getChildAt(0).getTop();
它通常會爲零或負數 - 顯示列表頂部和列表中第一個視圖的頂部之間的差異
感謝Jin35,這使我可以找到使用第一個可見位置和兒童身高的偏移量。 –
編輯: 我在這個班改進,以避免某些時刻,賽道是失去因觀點過於大而不能正確得到一個getTop()
這種新的解決方案採用了4跟蹤點:
確保我們始終有一個isSafeToTrack
等於true
import android.view.View;
import android.widget.AbsListView;
/**
* Created by budius on 16.05.14.
* This improves on Zsolt Safrany answer on stack-overflow (see link)
* by making it a detector that can be attached to any AbsListView.
* http://stackoverflow.com/questions/8471075/android-listview-find-the-amount-of-pixels-scrolled
*/
public class PixelScrollDetector implements AbsListView.OnScrollListener {
private final PixelScrollListener listener;
private TrackElement[] trackElements = {
new TrackElement(0), // top view, bottom Y
new TrackElement(1), // mid view, bottom Y
new TrackElement(2), // mid view, top Y
new TrackElement(3)};// bottom view, top Y
public PixelScrollDetector(PixelScrollListener listener) {
this.listener = listener;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// init the values every time the list is moving
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL ||
scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
for (TrackElement t : trackElements)
t.syncState(view);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
boolean wasTracked = false;
for (TrackElement t : trackElements) {
if (!wasTracked) {
if (t.isSafeToTrack(view)) {
wasTracked = true;
if (listener != null)
listener.onScroll(view, t.getDeltaY());
t.syncState(view);
} else {
t.reset();
}
} else {
t.syncState(view);
}
}
}
public static interface PixelScrollListener {
public void onScroll(AbsListView view, float deltaY);
}
private static class TrackElement {
private final int position;
private TrackElement(int position) {
this.position = position;
}
void syncState(AbsListView view) {
if (view.getChildCount() > 0) {
trackedChild = getChild(view);
trackedChildPrevTop = getY();
trackedChildPrevPosition = view.getPositionForView(trackedChild);
}
}
void reset() {
trackedChild = null;
}
boolean isSafeToTrack(AbsListView view) {
return (trackedChild != null) &&
(trackedChild.getParent() == view) && (view.getPositionForView(trackedChild) == trackedChildPrevPosition);
}
int getDeltaY() {
return getY() - trackedChildPrevTop;
}
private View getChild(AbsListView view) {
switch (position) {
case 0:
return view.getChildAt(0);
case 1:
case 2:
return view.getChildAt(view.getChildCount()/2);
case 3:
return view.getChildAt(view.getChildCount() - 1);
default:
return null;
}
}
private int getY() {
if (position <= 1) {
return trackedChild.getBottom();
} else {
return trackedChild.getTop();
}
}
View trackedChild;
int trackedChildPrevPosition;
int trackedChildPrevTop;
}
}
原來的答案:
首先,我要感謝@ zsolt-safrany爲他的答案,這是偉大的東西,他的全部榮譽。
但後來我想現在他的回答我的進步(仍是相當多的他的答案,只是一些改進)
改進:
這是一個獨立的「姿態探測器」型通過調用.setOnScrollListener()
可以添加到擴展AbsListView
的任何類中,因此這是一種更靈活的方法。
它使用滾動狀態的變化來預先分配跟蹤的孩子,所以它不會「浪費」一個onScroll
通過來分配其位置。
它重新計算每onScroll
通過跟蹤的孩子,以避免丟失隨機onScroll傳遞重新計算子。 (這可以通過緩存一些高度來提高效率,並且僅在一定量的滾動之後重新計算)。
希望它有助於
import android.view.View;
import android.widget.AbsListView;
/**
* Created by budius on 16.05.14.
* This improves on Zsolt Safrany answer on stack-overflow (see link)
* by making it a detector that can be attached to any AbsListView.
* http://stackoverflow.com/questions/8471075/android-listview-find-the-amount-of-pixels-scrolled
*/
public class PixelScrollDetector implements AbsListView.OnScrollListener {
private final PixelScrollListener listener;
private View mTrackedChild;
private int mTrackedChildPrevPosition;
private int mTrackedChildPrevTop;
public PixelScrollDetector(PixelScrollListener listener) {
this.listener = listener;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// init the values every time the list is moving
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL ||
scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
if (mTrackedChild == null) {
syncState(view);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mTrackedChild == null) {
// case we don't have any reference yet, try again here
syncState(view);
} else {
boolean childIsSafeToTrack = (mTrackedChild.getParent() == view) && (view.getPositionForView(mTrackedChild) == mTrackedChildPrevPosition);
if (childIsSafeToTrack) {
int top = mTrackedChild.getTop();
if (listener != null) {
float deltaY = top - mTrackedChildPrevTop;
listener.onScroll(view, deltaY);
}
// re-syncing the state make the tracked child change as the list scrolls,
// and that gives a much higher true state for `childIsSafeToTrack`
syncState(view);
} else {
mTrackedChild = null;
}
}
}
private void syncState(AbsListView view) {
if (view.getChildCount() > 0) {
mTrackedChild = getChildInTheMiddle(view);
mTrackedChildPrevTop = mTrackedChild.getTop();
mTrackedChildPrevPosition = view.getPositionForView(mTrackedChild);
}
}
private View getChildInTheMiddle(AbsListView view) {
return view.getChildAt(view.getChildCount()/2);
}
public static interface PixelScrollListener {
public void onScroll(AbsListView view, float deltaY);
}
}
這裏的[如何](http://stackoverflow.com/questions/12727594/android-listview-current-scroll-location-y-pixels/35594825#35594825 ) – Sarasranglt