Puis-je avoir onScrollListener pour un ScrollView?

J’utilise un HorizontalScrollView dans une mise en page et j’ai besoin d’identifier l’utilisateur qui a atteint le début et la fin du défilement.

Pour ListView j’ai essayé le onScrollListener et il est possible de trouver le début et la fin du défilement.

J’ai essayé de faire la même chose dans mon Scrollview mais cela semble impossible. Y a-t-il d’autres moyens possibles d’atteindre ce dont j’ai besoin?

Merci d’avance.

Chaque instance de View appelle getViewTreeObserver() . Maintenant, lorsque vous tenez une instance de ViewTreeObserver , vous pouvez lui append un OnScrollChangedListener() à l’aide de la méthode addOnScrollChangedListener() .

Vous pouvez voir plus d’informations sur cette classe ici .

Il vous permet de connaître chaque événement de défilement – mais sans les coordonnées. Vous pouvez les obtenir en utilisant getScrollY() ou getScrollX() depuis l’écouteur.

 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 } }); 

Cela pourrait être très utile. Utilisez NestedScrollView au lieu de ScrollView . Support Library 23.1 a introduit un OnScrollChangeListener à NestedScrollView . Donc, vous pouvez faire quelque chose comme ça.

  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 } }); 

Voici un HorizontalScrollView dérivé que j’ai écrit pour gérer les notifications concernant le défilement et la fin du défilement. Il gère correctement lorsqu’un utilisateur a cessé de faire défiler activement et lorsqu’il décélère complètement après qu’un utilisateur l’a laissé aller:

 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, AtsortingbuteSet attrs) { this(context, attrs, 0); } public ObservableHorizontalScrollView(Context context, AtsortingbuteSet 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; } } 

Si vous souhaitez connaître la position de défilement d’une vue, vous pouvez utiliser la fonction d’extension suivante dans la classe View:

 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 } } } 

Utilisez NestedScrollView.

https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.OnScrollChangeListener.html

 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--------- 

Vous pouvez utiliser NestedScrollView au lieu de ScrollView . Toutefois, lorsque vous utilisez un Kotlin Lambda, vous ne saurez pas si vous voulez que setOnScrollChangeListener de setOnScrollChangeListener au lieu de celui de View (qui est le niveau 23 de l’API). Vous pouvez résoudre ce problème en spécifiant le premier paramètre en tant que NestedScrollView.

 nestedScrollView.setOnScrollChangeListener { _: NestedScrollView, scrollX: Int, scrollY: Int, _: Int, _: Int -> Log.d("ScrollView", "Scrolled to $scrollX, $scrollY") }