OnTouchListenerを使用してAndroidでダブルタップイベントをキャッチする方法
-
26-10-2019 - |
質問
OnTouchListenerを使用してダブルタップイベントをキャッチしようとしています。 MotionEvent.action_Downの長さを設定し、2番目のMotionEvent.action_Downのために異なる長い長さを設定し、2つの間の時間を測定してから、それを使用して何かをします。しかし、私はこれにアプローチする方法を正確に理解するのに苦労しています。私はスイッチケースを使用してマルチタッチイベントをピックアップしているので、GestureDetectorを実装するためにこれをすべてリトールしようとしたくない(残念ながら、OntouchListenerとGestureDetectorの両方を同時に実装することは不可能です)。どんなアイデアも大いに役立ちます:
i.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
ImageView i = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
long firstTouch = System.currentTimeMillis();
///how to grab the second action_down????
break;
解決
この問題に先ほど取り上げました。ハンドラーを使用して、2回目のクリックを待つために一定の時間を待つことが含まれます。 メニューボタンが押されたら、シングルクリックイベントとダブルクリックイベントを作成するにはどうすればよいですか?
他のヒント
クラスで定義:
public class main_activity extends Activity
{
//variable for counting two successive up-down events
int clickCount = 0;
//variable for storing the time of first click
long startTime;
//variable for calculating the total time
long duration;
//constant for defining the time duration between the click that can be considered as double-tap
static final int MAX_DURATION = 500;
}
それからあなたのクラスの体で:
OnTouchListener MyOnTouchListener = new OnTouchListener()
{
@Override
public boolean onTouch (View v, MotionEvent event)
{
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
startTime = System.currentTimeMillis();
clickCount++;
break;
case MotionEvent.ACTION_UP:
long time = System.currentTimeMillis() - startTime;
duration= duration + time;
if(clickCount == 2)
{
if(duration<= MAX_DURATION)
{
Toast.makeText(captureActivity.this, "double tap",Toast.LENGTH_LONG).show();
}
clickCount = 0;
duration = 0;
break;
}
}
return true;
}
}
これは、以下の回答から採用されました。 AndroidのDoubleTap に https://stackoverflow.com/users/1395802/karn
ヘルパークラスのsimplegesturelistenerを使用すると、GesturelistenerとOndoubletaplistenerを実装することで、あまり必要ありません。
yourView.setOnTouchListener(new OnTouchListener() {
private GestureDetector gestureDetector = new GestureDetector(Test.this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.d("TEST", "onDoubleTap");
return super.onDoubleTap(e);
}
... // implement here other callback methods like onFling, onScroll as necessary
});
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TEST", "Raw event: " + event.getAction() + ", (" + event.getRawX() + ", " + event.getRawY() + ")");
gestureDetector.onTouchEvent(event);
return true;
}});
それははるかに簡単です:
//variable for storing the time of first click
long startTime;
//constant for defining the time duration between the click that can be considered as double-tap
static final int MAX_DURATION = 200;
if (event.getAction() == MotionEvent.ACTION_UP) {
startTime = System.currentTimeMillis();
}
else if (event.getAction() == MotionEvent.ACTION_DOWN) {
if(System.currentTimeMillis() - startTime <= MAX_DURATION)
{
//DOUBLE TAP
}
}
これが私の解決策です。
「シングルタップ」と「ダブルタップ」の高速で明確な分離を持つことが重要でした。私は試した GestureDetector
最初は非常に悪い結果がありました。たぶん、私のscrollviewsのネストされた使用の結果です - 誰が知っていますか...
私は焦点を合わせます MotionEvent.ACTION_UP
タップされた要素のID。最初のタップを生かし続けるには、aを使用します Handler
遅延メッセージ(350ms)を送信して、ユーザーが2回目のタップを配置する時間があるので ImageView
. 。ユーザーが同一のIDを使用して要素を2番目のタップに配置した場合、これをダブルタップとして使用し、遅延メッセージを削除し、「ダブルタップ」のカスタムコードを実行しました。ユーザーが別のIDを持つ要素にタップを配置した場合、私はこれを新しいタップとして取得し、別のタップを作成します Handler
それのための。
クラスのグローバル変数
private int tappedItemId = -1;
Handler myTapHandler;
final Context ctx = this;
コードの例
ImageView iv = new ImageView(getApplicationContext());
//[...]
iv.setId(i*1000+n);
iv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP: {
//active 'tap handler' for current id?
if(myTapHandler != null && myTapHandler.hasMessages(v.getId())) {
// clean up (to avoid single tap msg to be send and handled)
myTapHandler.removeMessages(tappedItemId);
tappedItemId = -1;
//run 'double tap' custom code
Toast.makeText(ScrollView.this, "double tap on "+v.getId(), Toast.LENGTH_SHORT).show();
return true;
} else {
tappedItemId = v.getId();
myTapHandler = new Handler(){
public void handleMessage(Message msg){
Toast.makeText(ctx, "single tap on "+ tappedItemId + " msg 'what': " + msg.what, Toast.LENGTH_SHORT).show();
}
};
Message msg = Message.obtain();
msg.what = tappedItemId;
msg.obj = new Runnable() {
public void run() {
//clean up
tappedItemId = -1;
}
};
myTouchHandler.sendMessageDelayed(msg, 350); //350ms delay (= time to tap twice on the same element)
}
break;
}
}
return true;
}
});