Могу ли я иметь onScrollListener для ScrollView?
Я использую HorizontalScrollView
в макете, и мне нужно определить, что пользователь достиг начальной и конечной точки прокрутки.
на ListView
Я пробовал onScrollListener
и можно найти начальную и конечную точку прокрутки.
Я попытался сделать то же самое в моем Scrollview
но это кажется невозможным. Есть ли другие возможные способы достичь того, что мне нужно.
спасибо заранее.
7 ответов:
каждый экземпляр View вызывает
getViewTreeObserver()
. Теперь при удержании экземпляраViewTreeObserver
, вы можете добавитьOnScrollChangedListener()
С помощью методаaddOnScrollChangedListener()
.вы можете увидеть дополнительную информацию об этом классе здесь.
это позволяет вам быть в курсе каждого события скроллинга - но без координат. Вы можете получить их с помощью
getScrollY()
илиgetScrollX()
изнутри слушателя, хотя.scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() { @Override public void onScrollChanged() { int scrollY = rootScrollView.getScrollY(); // For ScrollView int scrollX = rootScrollView.getScrollX(); // For HorizontalScrollView // DO SOMETHING WITH THE SCROLL COORDINATES } });
Это может быть очень полезно. Используйте
NestedScrollView
вместоScrollView
. Библиотека поддержки 23.1 введенOnScrollChangeListener
доNestedScrollView
. Так что вы можете сделать что-то подобное.myScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { Log.d("ScrollView","scrollX_"+scrollX+"_scrollY_"+scrollY+"_oldScrollX_"+oldScrollX+"_oldScrollY_"+oldScrollY); //Do something } });
вот производный HorizontalScrollView, который я написал для обработки уведомлений о прокрутке и завершении прокрутки. Он правильно обрабатывает, когда пользователь перестал активно прокручивать и когда он полностью замедляется после того, как пользователь отпускает:
public class ObservableHorizontalScrollView extends HorizontalScrollView { public interface OnScrollListener { public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY); public void onEndScroll(ObservableHorizontalScrollView scrollView); } private boolean mIsScrolling; private boolean mIsTouching; private Runnable mScrollingRunnable; private OnScrollListener mOnScrollListener; public ObservableHorizontalScrollView(Context context) { this(context, null, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); if (action == MotionEvent.ACTION_MOVE) { mIsTouching = true; mIsScrolling = true; } else if (action == MotionEvent.ACTION_UP) { if (mIsTouching && !mIsScrolling) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(this); } } mIsTouching = false; } return super.onTouchEvent(ev); } @Override protected void onScrollChanged(int x, int y, int oldX, int oldY) { super.onScrollChanged(x, y, oldX, oldY); if (Math.abs(oldX - x) > 0) { if (mScrollingRunnable != null) { removeCallbacks(mScrollingRunnable); } mScrollingRunnable = new Runnable() { public void run() { if (mIsScrolling && !mIsTouching) { if (mOnScrollListener != null) { mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this); } } mIsScrolling = false; mScrollingRunnable = null; } }; postDelayed(mScrollingRunnable, 200); } if (mOnScrollListener != null) { mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY); } } public OnScrollListener getOnScrollListener() { return mOnScrollListener; } public void setOnScrollListener(OnScrollListener mOnEndScrollListener) { this.mOnScrollListener = mOnEndScrollListener; } }
Если вы хотите знать положение прокрутки представления, то вы можете использовать следующую функцию расширения для класса представления:
fun View?.onScroll(callback: (x: Int, y: Int) -> Unit) { var oldX = 0 var oldY = 0 this?.viewTreeObserver?.addOnScrollChangedListener { if (oldX != scrollX || oldY != scrollY) { callback(scrollX, scrollY) oldX = scrollX oldY = scrollY } } }
Использовать NestedScrollView.
scrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { } });
// --------Start Scroll Bar Slide-------- final HorizontalScrollView xHorizontalScrollViewHeader = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewHeader); final HorizontalScrollView xHorizontalScrollViewData = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewData); xHorizontalScrollViewData.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { int scrollX; int scrollY; scrollX=xHorizontalScrollViewData.getScrollX(); scrollY=xHorizontalScrollViewData.getScrollY(); xHorizontalScrollViewHeader.scrollTo(scrollX, scrollY); } }); // ---------End Scroll Bar Slide---------
можно использовать
NestedScrollView
вместоScrollView
. Однако при использовании лямбды Kotlin он не будет знать, что вы хотите NestedScrollViewsetOnScrollChangeListener
вместо одного в представлении (который является уровнем API 23). Вы можете исправить это, указав первый параметр в качестве NestedScrollView.nestedScrollView.setOnScrollChangeListener { _: NestedScrollView, scrollX: Int, scrollY: Int, _: Int, _: Int -> Log.d("ScrollView", "Scrolled to $scrollX, $scrollY") }