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()が呼ばれるようになりました。