2013-10-02 17 views
7

Przesłałem ScrollView, aby przekazać MotionEvent s do GestureDetector, aby wykryć zdarzenia rzutu na ScrollView. Muszę być w stanie wykryć, kiedy przewijanie się zatrzymuje. Nie pokrywa się to ze zdarzeniem MotionEvent.ACTION_UP, ponieważ zazwyczaj dzieje się to na początku gestu rzucania, po którym następuje seria wywołań onScrollChanged() w widoku przewijania.Wykryj koniec rzucania na ScrollView

Więc w zasadzie to, co mamy do czynienia ze tutaj jest następujące zdarzenia:

  1. onFling
  2. onScrollChanged, onScrollChanged, onScrollChanged, ..., onScrollChanged

Nie ma oddzwanianie do kiedy Zdarzenia onScrollChanged są uruchamiane. Myślałem o wysłaniu wiadomości do kolejki zdarzeń za pomocą Handler podczas onFling i czekając na wykonanie Runnable, aby zasygnalizować koniec rzutu, niestety wystrzeliwuje po pierwszym wywołaniu onScrollChanged.

Jakieś inne pomysły?

+0

Tak, jak wspomniałem w moim pytaniu, że podejście nie działa. –

+0

Czy widziałeś/wypróbowałeś moją odpowiedź? –

Odpowiedz

15

Połączyłem kilka odpowiedzi z here, aby skonstruować działający obiekt nasłuchujący, który przypomina sposób, w jaki robi to AbsListView. Zasadniczo to opisujesz i działa dobrze w moich testach.

Uwaga: można po prostu zastąpić ScrollView.fling(int velocityY) zamiast używać własnego GestureDetector.

import android.content.Context; 
import android.util.AttributeSet; 
import android.widget.ScrollView; 

public class CustomScrollView extends ScrollView { 

    private static final int DELAY_MILLIS = 100; 

    public interface OnFlingListener { 
     public void onFlingStarted(); 
     public void onFlingStopped(); 
    } 

    private OnFlingListener mFlingListener; 
    private Runnable mScrollChecker; 
    private int mPreviousPosition; 

    public CustomScrollView(Context context) { 
     this(context, null, 0); 
    } 

    public CustomScrollView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public CustomScrollView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 

     mScrollChecker = new Runnable() { 
      @Override 
      public void run() { 
       int position = getScrollY(); 
       if (mPreviousPosition - position == 0) { 
        mFlingListener.onFlingStopped(); 
        removeCallbacks(mScrollChecker); 
       } else { 
        mPreviousPosition = getScrollY(); 
        postDelayed(mScrollChecker, DELAY_MILLIS); 
       } 
      } 
     }; 
    } 

    @Override 
    public void fling(int velocityY) { 
     super.fling(velocityY); 

     if (mFlingListener != null) { 
      mFlingListener.onFlingStarted(); 
      post(mScrollChecker); 
     } 
    } 

    public OnFlingListener getOnFlingListener() { 
     return mFlingListener; 
    } 

    public void setOnFlingListener(OnFlingListener mOnFlingListener) { 
     this.mFlingListener = mOnFlingListener; 
    } 

} 
+0

Nie próbowałem tego, ale stałe wiadomości w wątku UI może być problem z wydajnością nie? –

+1

Biorąc pod uwagę, że jest to podobne do sposobu, w jaki zrobiono to za pomocą 'Scroller' w' AbsListView', myślę, że nic ci nie będzie. Aktualizują się co 40 ms. Sprawdź 'AbsListView.FlingRunnable' –