【Android】onLongPressを使わないで長押し判定
背景
View上で長押しを判定したい時、通常はGestureDetectorクラスのOnGestureListenerをimplementsしてonLongPressを実装する。
GestureDetector | Android Developers
参考サイト
Androidプログラミングの館
Android タッチパネルのダブルタップや長押しを検出する方法 | TechBooster
しかしonLongPressは長押し判定の時間を指定できない。
今作ってるマインスイーパアプリでは長押しでフラグを立てる処理にしている。
onLongPressで長押し判定を実装すると、0.8秒程度押し続けないとならない。
0.8秒という時間は長く、ユーザーはスピーディーにフラグを立てることができなくてイライラしてしまう。
解決策
onTouchEventで取得できるMotionEvent.ACTION_DOWNとHandlerクラスを使う。
onTouchEventはViewクラスで画面がタッチされたときに呼び出されるメソッド。
詳しくはこちら
Androidでアプリ画面のタッチイベントを取得する方法 | TechBooster
Handlerクラスは「指定した時間後に処理を行いたい」という時に使い、処理の中身はRunnableクラスのrun()メソッドで実装する。
詳しくはこちら
[Android]指定した時間後にちょっとした処理を行う方法 | Developers.IO
結局長押し判定はこんなコードになる。convertCoordinateToAddress()は現在の座標からマス番号を求めるメソッド。
とりあえずACTION_DOWNが検出されたらhandlerを起動して、0.4秒後にrunメソッドを実行する。
0.4秒を測ってる間に指上げなどの邪魔が入ったらhandlerを中止する。
参考サイト
java - Detecting a long press with Android - Stack Overflow
【MainActivity.java】
/*略*/ long LONG_PRESS_TIME = 400; // 長押し時間(ミリ秒) Handler long_press_handler = new Handler(); Runnable long_press_receiver = new Runnable() { @Override public void run() { // 長押しする longClickSquare(); } }; /*略*/ @Override public boolean onTouchEvent( MotionEvent e ) { switch ( e.getAction() ) { case MotionEvent.ACTION_DOWN: // 指が触れたとき action_down_square_address = game_view.convertCoordinateToAddress(e.getX(), e.getY()); // 触れたマス番号を記憶 long_press_handler.postDelayed( long_press_receiver, LONG_PRESS_TIME); // 長押し判定 break; case MotionEvent.ACTION_UP: // 指を上げたとき long_press_handler.removeCallbacks( long_press_receiver ); // 長押し中に指を上げたらhandlerの処理を中止 break; case MotionEvent.ACTION_MOVE : // 指でなぞったとき // 触れたマスが最初に触れていたマスと違う番号なら if ( game_view.convertCoordinateToAddress(e.getX(), e.getY()) != action_down_square_address ) { long_press_handler.removeCallbacks( long_press_receiver ); // 最初に触れたマスから離れたらhandlerの処理を中止 } break; default: break; } return false; } } /*略*/