◆PROCESSING 逆引きリファレンス
カテゴリー:スマホ(AndroidMode)
長押しを検知するには(AndroidMode編)
【概要】
PROCESSINGにAndroidMode を導入する事で、PROCESSINGで開発したプログラムをAndroid端末上で動かす事ができるようになります。
AndroidModeの導入については「PROCESSINGをAndroid端末で動かすには(4.0版)」記事を参照してください。
長押しとは、タップした状態で指を動かさずに画面を数秒間押し続け、そこから指を離す操作です。何かを選択する操作などに利用します。
指を離さずに押し続ける操作を「タッチアンドホールド」と呼ぶこともあります。
(画像URL:illust-AC 様:かみたまさん、amiyaoさん)
AndroidModeで画面の長押しを検知するには、surfaceTouchEvent 関数とAndroid SDKの GestureDetector # SimpleOnGestureListener を併用して判別します。
surfaceTouchEvent 関数やタッチ系イベント関数( touchStarted など)だけを利用しても頑張れば検知可能ですが、GestureDetector クラスを併用した方が楽ちんです(笑)。
GestureDetector クラスの詳細については「スワイプを検知するには(AndroidMode編)」記事を参照して下さい。
SimpleOnGestureListener を継承したクラス内で onLongPressメソッドをオーバライドする事で、長押しを検知することができるようになります。
【詳細】
長押しイベント
イベントvoid onLongPress( MotionEvent e ){ }
e:発生したMotionEvent
SimpleOnGestureListener を継承したクラスで、上記メソッドをオーバライドします。
1 2 3 4 5 6 7 8 9 10 11 12 |
//ジェスチャー検知クラス //SimpleOnGestureListener クラスを継承した専用のクラスを用意する class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); //あれやこれや、行いたい処理を記述 return; } } |
こんな感じです。
このイベントはマルチタップに対応していない事に注意が必要です。2本以上の指で同時に長押しすると、イベントが呼び出されません。
また、長押しではなくタッチアンドホールドに反応するイベントとなっている点にも注意が必要です。
手元の環境で試した範囲では、おおよそ0.6秒以上タップし続けると、指を離していなくても本イベントが発生します。
指を離した時にイベントを検知したい場合や、複数の指での長押しを検知したい場合は、surfaceTouchEvent 関数やタッチ系イベント関数( touchStarted など)を利用して自力で検知する必要があります。
【関連記事】
- タップを検知するには(AndroidMode編)
- フリック検知するには(AndroidMode編)
- ダブルタップを検知するには(AndroidMode編)
- スワイプを検知するには(AndroidMode編)
- ピンチを検知するには(AndroidMode編)
- ローテートを検知するには(AndroidMode編)
- 様々なタッチ操作を検知するには(Ke:tai.lib 編)
サンプルプログラム
タッチアンドホールドを検知する例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
import android.app.Activity; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.view.GestureDetector; import android.view.MotionEvent; import processing.core.PApplet; /** * PROCESSING AndroidMode 長押し検知 Sample * @author MSLABO * @version 1.0 2018/02 */ public class Sketch extends PApplet { Activity act; //Activity Context con; //Context GestureDetector gestureDetector; //ジェスチャーOBJ float x, y; //イベント座標 /** * ジェスチャー検知クラス */ class MyGestureListener extends GestureDetector.SimpleOnGestureListener { /** * タッチアンドホールドイベント関数 * @param e イベント内容 */ @Override public void onLongPress(MotionEvent e) { super.onLongPress(e); //イベントが発生した座標を取得する int pIndex = e.getActionIndex(); x = e.getX(pIndex); y = e.getY(pIndex); } } @Override public void settings() { //フルスクリーン fullScreen(); } Process process; @Override public void setup() { //ActivityとContextを取得 act = getActivity(); con = act.getApplicationContext(); //文字描画準備 textAlign(LEFT,TOP); textSize(16 * displayDensity); x = y = -1; //UIスレッドのLooperと連携したHandlerを作成して //GestureDetectorに与える Handler mHandler = new Handler(Looper.getMainLooper()); gestureDetector = new GestureDetector(con, new MyGestureListener(), mHandler); } @Override public void draw() { background( 200 ); if( x > -1 && y > -1 ){ //タッチアンドホールドされていたら座標を表示する fill(0); text( "LognTap x=" + x + " y=" + y, 0, 0); fill(color(100,100,255)); ellipse(x,y,30,30); } } @Override public boolean surfaceTouchEvent(MotionEvent motionEvent) { //GestureDetectorにイベントを渡す gestureDetector.onTouchEvent(motionEvent); return super.surfaceTouchEvent(motionEvent); } } |
画面をタッチアンドホールドされたら、その座標を表示します。
指を離した時に長押しを検知する例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
import android.graphics.Point; import android.util.Log; import android.view.MotionEvent; import processing.core.PApplet; /** * PROCESSING AndroidMode 長押し検知 Sample * @author MSLABO * @version 1.1 2018/02 */ public class Sketch extends PApplet { private ManyPointInfo manyPointInfo; /** * Tapされた場所と時間を管理するクラス */ class PointInfo{ private int tId; //Tapインデックス private Point tPoint; //Tap座標 private long tMillsLong; //Tap時間 private long tMillsStart; //Tap開始時間 private boolean longTapFlg; //長押しFLG PointInfo(){ Clear(); } void Clear(){ tId = -1; tPoint = null; tMillsStart = 0; tMillsLong = 0; longTapFlg = false; } void Copy(PointInfo _info){ tId = _info.tId; if( _info.tPoint != null ){ tPoint = new Point(_info.tPoint.x, _info.tPoint.y); } else { tPoint = null; } tMillsStart = _info.tMillsStart; tMillsLong = _info.tMillsLong; longTapFlg = _info.longTapFlg; } void Set(int _index, float _x, float _y){ tId = _index; tPoint = new Point((int)_x, (int)_y); tMillsStart = System.currentTimeMillis(); tMillsLong = 0; longTapFlg = false; } } /** * Tapされた場所を複数管理するクラス */ class ManyPointInfo { final int MAX_POINT = 2; //マルチタップ対応指数 final long FIRE_MILLS = 600; //長押し閾値 final Object lock; //排他オブジェクト PointInfo InfoList[] = new PointInfo[MAX_POINT]; ManyPointInfo(){ lock = new Object(); int i = 0; //MAX_POINT 数の管理領域を作成する while (i < MAX_POINT) { InfoList[i] = new PointInfo(); i++; } } void SetTapInfo(int _id, float _x, float _y ){ synchronized(lock) { //空き領域を見つけたら、Tap開始情報をセットする for (PointInfo info : InfoList) { if (info.tId < 0) { info.Set(_id, _x, _y); break; } } } } PointInfo GetTapInfo(int _index){ //指定位置のTap情報を複写して戻す PointInfo retInfo = new PointInfo(); synchronized(lock) { retInfo.Copy(InfoList[_index]); } return retInfo; } void ClearTapInfo(int _index){ //指定位置のTap情報を初期化する synchronized(lock){ InfoList[_index].Clear(); } } int GetCount(){ //管理しているTap情報数を戻す return InfoList.length; } //長押し判定関数 void CheckFire(int _id){ synchronized(lock){ for (PointInfo info : InfoList) { if (info.tId == _id) { //所定より長い時間Tapされていた場合、長押しとみなす long NowTime = System.currentTimeMillis(); long TapTime = NowTime - info.tMillsStart; if (TapTime > FIRE_MILLS) { Log.d("AMTEST", "LongTap Done ID=" + _id + " Time=" + TapTime); info.longTapFlg = true; info.tMillsLong = TapTime; break; } //長押しではなかった指が離れた情報は初期化 info.Clear(); } } } } } @Override public void settings() { //フルスクリーン fullScreen(); } @Override public void setup() { //文字描画準備 textAlign(LEFT,TOP); textSize(12 * displayDensity); //マルチタップで長押しを管理するためのクラス生成 manyPointInfo = new ManyPointInfo(); background( 200 ); } @Override public void draw() { //長押しされた位置を描画する for ( int i = 0; i < manyPointInfo.GetCount(); i++ ) { PointInfo tapP = manyPointInfo.GetTapInfo(i); if( tapP.longTapFlg){ fill(color(100,100,255)); ellipse(tapP.tPoint.x, tapP.tPoint.y, 30, 30); fill(0); text( tapP.tMillsLong, tapP.tPoint.x + 10, tapP.tPoint.y + 10); manyPointInfo.ClearTapInfo(i); } } } @Override public boolean surfaceTouchEvent(MotionEvent motionEvent) { int Action = motionEvent.getActionMasked(); int tIndex = motionEvent.getActionIndex(); int tId = motionEvent.getPointerId(tIndex); if( Action == MotionEvent.ACTION_DOWN || Action == MotionEvent.ACTION_POINTER_DOWN){ //タッチ開始時、座標を記録する manyPointInfo.SetTapInfo(tId, motionEvent.getX(tIndex), motionEvent.getY(tIndex)); } if( Action == MotionEvent.ACTION_POINTER_UP || Action == MotionEvent.ACTION_UP){ //タッチ終了時、長押しされたか判定する manyPointInfo.CheckFire(tId); } return super.surfaceTouchEvent(motionEvent); } } |
自力でロングタップを検知する例です。
FIRE_MILLS ミリセカンド以上、同じ場所をタップされていたら「長押し」と判定します。
onLongPressとは異なり、指を離した時に判定を行います。またMAX_POINT 本までのマルチタップに対応します。
本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。