2013-10-02 4 views
7

MotionEvent을 으로 바꾸어 ScrollView에서 fling 이벤트를 감지하도록 ScrollView을 재정의했습니다. 나는 스크롤이 멈출 때를 감지 할 수 있어야한다. 이것은 보통 MotionEvent.ACTION_UP 이벤트와 일치하지 않습니다. 대개 플 래밍 제스처가 시작될 때 발생하며, 그 다음에 ScrollView에서 onScrollChanged() 호출이 발생합니다.ScrollView에서 fling의 끝을 감지

그러니까 기본적으로 우리가 여기서 다루고있는 것은 다음과 같은 이벤트입니다 :

  1. onFling
  2. onScrollChanged, onScrollChanged, onScrollChanged, ..., onScrollChanged 콜백이 때를 위해 없습니다

onScrollChanged 이벤트가 실행됩니다. onFling 중에 Handler을 사용하여 이벤트 대기열에 메시지를 게시하고 Runnable이 플링의 끝을 알리기를 기다리는 것을 생각하고있었습니다. 불행히도 첫 번째 onScrollChanged 호출 이후에 발생합니다.

다른 아이디어?

+0

예, 질문에 언급했듯이 접근 방식이 작동하지 않습니다. –

+0

본 적이 있습니까/내 대답 봤어? –

답변

15

here의 답변 중 몇 가지를 결합하여 AbsListView과 유사한 방식으로 작동하는 수신기를 구성했습니다. 그것은 본질적으로 당신이 묘사하는 것이며, 제 테스트에서 잘 작동합니다.

참고 : GestureDetector을 사용하는 대신 ScrollView.fling(int velocityY)을 간단하게 무시할 수 있습니다.

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

이 방법을 사용하지는 않았지만 UI 스레드의 상수 메시지는 성능 문제가 아닐 수 있습니다. –

+1

이 방법이'AbsListView'에서'Scroller'를 사용하는 것과 비슷하다고 생각합니다. 괜찮을 것 같습니다. 실제로 40ms마다 업데이트됩니다. 'AbsListView.FlingRunnable'을 확인하십시오. –