onScroll()というかonTouchEvent()が呼ばれない


Pocket

View上で指をスライドさせたイベントが取れないときの対処法です。

はまったところ

android.viewを継承したクラスを作ってGestureDetector.OnGestureListenerを実装したんだけど、なぜかonScroll()が呼ばれない。

onDown(),onShowPress()とかは呼ばれてるんだけど・・・なぜ?

@Override
public boolean onTouchEvent(MotionEvent event) {
   return mGestureDetector.onTouchEvent(event);
}

@Override
public boolean onDown(MotionEvent e) {
    //TODO Auto-generated method stub
    return false;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    //処理
    return true;
}

@Override
public boolean onLongPress(MotionEvent e) {
    //処理
    return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    //処理
    return true;
}

@Override
public boolean onShowPress(MotionEvent e) {
    //処理
    return true;
}

どうやらViewをタップした時にonTouchEvent()が呼ばれるけど、そのまま指をスライドした場合はonTouchEvent()が呼ばれてないようだ。
(ActivityのonTouchEvent()は呼ばれているけど…どうしてだろう??)

 

原因

画面を指で触ったときの最初のイベント(MotionEvent.ACTION_DOWN)に対してTrueを返していないため。
つまり、onDown()又は、onTouchEvent()でTrueを返す必要があった。

@Override
public boolean onTouchEvent(MotionEvent event) {
    mGestureDetector.onTouchEvent(event);
    return true; //←こうする
}

@Override
public boolean onDown(MotionEvent e) {
    //TODO Auto-generated method stub
    return true; //←又は、こうする
}

onTouchEvent()の戻り値は、発生した一連(始めに画面に触れてから指を離すまでの間)のタッチイベントを、ここでハンドリングするかしないかを返す必要があった。
#イベントを処理したらTrueを返すとう誤った認識をしていました(´・ω・`)

つまり、最初に発生するイベント=ACTION_DOWNに対して、
・trueを返す → ACTION_MOVEやUPの時にもonTouchEvent()が呼ばれる = このViewで一連のイベントを処理する
・falseを返す → ACTION_MOVEやUPの時にはonTouchEvent()が呼ばれない = このViewよりも下のViewへイベントを流す
ということみたいです。

参考
Input EventsのEvent Handlers辺り
ViewGroup.onInterceptTouchEvent

#正確に意味を読み取れているかあやしいので間違ってたらすいません

とりあえず上記のように修正したら、指を動かしたときにonScroll()が呼ばれるようになりました。

 
 

Leave a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です