2012-05-23 9 views
103

レイアウトでHorizontalScrollViewを使用していて、ユーザーがスクロールの開始点と終了点に達したことを確認する必要があります。ScrollViewのonScrollListenerを使用できますか?

ListView私はonScrollListenerを試しました。スクロールの開始点と終了点を見つけることができます。

私はScrollviewで同じことを試みましたが、それは不可能と思われます。私が必要とするものを達成する他の方法がありますか?

ありがとうございます。

+3

ことが可能です。 user2695685の回答を参照してください。要約すると、 'onStart'の次のようなことが、このトリックを行います:' hsv.getViewTreeObserver()。addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener(){@Override public void onScrollChanged(){Log.i(TAG、 "scroll:" + hsv。 onStart()の 'hsv'は' Horizo​​ntalScrollView'で動作します。 – JohnnyLambada

+0

誰かが役に立つ答えを受け入れる...それ以外の場合はあなた自身の答えを投稿してください。 –

+7

なぜScrollViewでスクロールイベントが検出されないのですか?これはナッツイモです。 – worked

答えて

310

ビューのすべてのインスタンスは、getViewTreeObserver()を呼び出します。今度はViewTreeObserverのインスタンスを保持するときはaddOnScrollChangedListener()というメソッドを使用してOnScrollChangedListener()を追加できます。

このクラスの詳細については、hereを参照してください。

これにより、すべてのスクロールイベントを認識できますが、座標はありません。あなたはリスナーの中から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 
    } 
}); 
+3

この回答は正しいとマークする必要があります。 ();}};} on.Start(); // hsv.getViewTreeObserver()。addOnScrollChangedListener()新しいViewTreeObserver.OnScrollChangedListener(){@オーバーライドpublic void onScrollChanged(){ )ここで 'hsv'は' Horizo​​ntalScrollView'です。私は同じことがScrollViewでもうまくいくと思う。 – JohnnyLambada

+3

。これは最高の答えです。 Horizo​​ntalScrollViewを拡張する必要はありません。 ScrollViewでテストしただけで、うまくいきます: final ScrollView sv =(ScrollView)findViewById(R.id.scrollViewArticle); sv.getViewTreeObserver()。addOnScrollChangedListener(新しいViewTreeObserver.OnScrollChangedListener()onScrollChanged { @Override公共ボイド(){ Log.d( "onScrollChanged Y"、String.valueOf(SV。getScrollY())); } }); –

+5

これは正解とマークする必要があります。 –

14

私はスクロールとスクロールの終了に関する通知を処理するために書いた派生Horizo​​ntalScrollViewです。

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

} 
+0

ViewTreeObserverメソッドを使用するよりも優れているようです。 ListViewsとScrollViewsを使用して複数のフラグメントがロードされているアクティビティ(たとえば、スライディングタブ付きの3つのフラグメント)がある場合、特定のビューのイベントを登録する必要があるからです。一方、ViewTreeObserverが登録されている場合、ビューがアクティブなビューでなくてもイベントが発生します。 –

+3

@ZaBlanc - ScrollViewを保持する私のアクティビティからこのクラスとリスナーを初期化する方法を教えてください。私はそれをうまく実装しましたが、リスナーはまだ値を返しません。 –

+0

これは実際に動作します! sdk> 23の必要はありません:) –

31

これは非常に便利かもしれません:ユーザが行くことができます後、それは完全に減速したときに積極的にをスクロール停止しているとき、それは適切に処理します。 ScrollViewの代わりにNestedScrollViewを使用してください。サポートライブラリ23.1は、OnScrollChangeListenerNestedScrollViewを導入しました。 こういうことができます。

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

getViewTreeObserver()を使用してリスナーを追加したかどうかを確認するよりも簡単です。ありがとう! –

+0

しかし、NestedScrollViewを水平スクロールビューとして使用するにはどうすればよいですか? Canntが任意のリソースを見つける – GensaGames

+0

水平スクロールを使用する場合はどうすればよいですか? –

0
// --------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--------- 
+0

このコードはAPI17より低いバージョンで使用できます。 –

+0

誰もがバッターを理解できるコードをサポートするための説明を追加してください。 –

+0

このコードは別の[answer](https://stackoverflow.com/a/23365539/5728095)と非常に似ていますか? – Sergii

関連する問題