2013-08-01 6 views
10

Ich brauchte ein einzelnes tap touch erkennen in meiner benutzerdefinierten Ansicht der ontouch-Methode. Ich versuchte, die x- und y-Werte in ACTION-DOWN und ACTION-UP zu erhalten, und in ACTION-UP gab ich eine Bedingung, dass, wenn a die Werte von X und Y in ACTIONDOWN und ACTION-UP gleich sind, es als einen einzigen Tap nehmen .singletap Touch erkennen in Ontouch-Methode der Ansicht

Mein Code ist wie

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    if (!mSupportsZoom && !mSupportsPan) return false; 

    mScaleDetector.onTouchEvent(ev); 

    final int action = ev.getAction(); 
    switch (action & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: { 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     mLastTouchX = x; //here i get x and y values in action down 
     mLastTouchY = y; 
     mActivePointerId = ev.getPointerId(0); 

     break; 
    } 

    case MotionEvent.ACTION_MOVE: { 
     final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
     final float x = ev.getX(pointerIndex); 
     final float y = ev.getY(pointerIndex); 

     if (mSupportsPan && !mScaleDetector.isInProgress()) { 
      final float dx = x - mLastTouchX; 
      final float dy = y - mLastTouchY; 

      mPosX += dx; 
      mPosY += dy; 
      //mFocusX = mPosX; 
      //mFocusY = mPosY; 

      invalidate(); 
     } 

     mLastTouchX = x; 
     mLastTouchY = y; 

     break; 
    } 

    case MotionEvent.ACTION_UP: { 

     final float x = ev.getX(); 
     final float y = ev.getY(); 

     touchupX=x; //here is get x and y values at action up 
     touchupY=y; 

     if(mLastTouchX == touchupX && mLastTouchY == touchupY){ //my condition if both the x and y values are same . 

      PinchZoomPanActivity2.tapped1(this.getContext(), 100); //my method if the singletap is detected 

     } 
     else{ 

     } 

     mActivePointerId = INVALID_POINTER_ID; 

     break; 
    } 

    case MotionEvent.ACTION_CANCEL: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
    } 

    case MotionEvent.ACTION_POINTER_UP: { 
     final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
       >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     final int pointerId = ev.getPointerId(pointerIndex); 
     if (pointerId == mActivePointerId) { 

      final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
      mLastTouchX = ev.getX(newPointerIndex); 
      mLastTouchY = ev.getY(newPointerIndex); 
      mActivePointerId = ev.getPointerId(newPointerIndex); 
     } 
     break; 
    } 
    } 

    return true; 
} 

folgt, aber ich kann es nicht getan. Ich meine, bei jeder Aktion wird meine Methode aufgerufen. selbst wenn die x- und y-Werte von actionup und actiondown nicht gleich sind. und ich denke, ich muss auch etwas Abstand zum Singletap legen, während wir mit dem Finger auf dem Bildschirm berühren. Kann mir jemand einige Vorschläge machen?

+0

verwenden Es wird nie an genau derselben Stelle sein - dein Finger wird sich immer leicht bewegen. Verwenden Sie eine Bereichsprüfung - stellen Sie sicher, dass abs (upLoc-downLoc) <5. –

+0

Ich brauche Bereichsprüfung, aber ich habe nicht verstanden, Ihre "abs (upLoc-downLoc) <5". –

+0

abs = absoluter Wert. Das heißt also, wenn sich der Standort um weniger als 5 Pixel geändert hat. –

Antwort

6

Ich lief auch in letzter Zeit das gleiche Problem und am Ende musste ein Debounce implementieren, damit es funktioniert. Es ist nicht ideal, aber es ist ziemlich zuverlässig, bis ich etwas besseres finde.

View.onClickListener war viel zuverlässiger für mich, aber leider brauche ich das MotionEvent vom OnTouchListener.

Edit: Entfernt den überschüssigen Code, der es hier

class CustomView extends View { 

    private static long mDeBounce = 0; 

    static OnTouchListener listenerMotionEvent = new OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 
      if (Math.abs(mDeBounce - motionEvent.getEventTime()) < 250) { 
       //Ignore if it's been less then 250ms since 
       //the item was last clicked 
       return true; 
      } 

      int intCurrentY = Math.round(motionEvent.getY()); 
      int intCurrentX = Math.round(motionEvent.getX()); 
      int intStartY = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalY(0)) : intCurrentY; 
      int intStartX = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalX(0)) : intCurrentX; 

      if ((motionEvent.getAction() == MotionEvent.ACTION_UP) && (Math.abs(intCurrentX - intStartX) < 3) && (Math.abs(intCurrentY - intStartY) < 3)) { 
       if (mDeBounce > motionEvent.getDownTime()) { 
        //Still got occasional duplicates without this 
        return true; 
       } 

       //Handle the click 

       mDeBounce = motionEvent.getEventTime(); 
       return true; 
      } 
      return false; 
     } 
    }; 
} 
+1

Vielen Dank.dies funktioniert. Beste Funktionalität zu doubletap in ontouch nach mir. Sie können einige Störungen beim Multitouch finden, aber das ist das Beste. –

+0

funktioniert nicht für mich, das übersteuert sogar meine Doppelklick-Methode – Casper

0

Denken Sie, dass Sie nicht "gleich" Operator verwenden müssen. Verwenden Sie stattdessen ungefähr Wert

case MotionEvent.ACTION_DOWN: { 
    final int CONST = 5; 
    final float x = ev.getX(); 
    final float y = ev.getY(); 

    mLastTouchXMax = x+CONST; //here i get x and y values in action down 
    mLastTouchXMin = x-CONST; 
    mLastTouchYMax = y+CONST; 
    mLastTouchYMin = y-CONST; 
    mActivePointerId = ev.getPointerId(0); 

    break; 
} 

Und in ACTION_UP überprüfen X und Y Werte zwischen Intervall.

+0

Ich habe nicht verstanden, was in Aktion Up zu tun ist. Ich muss überprüfen, ob x und y Werte in Aktion bis unter die vier Werte in Aktion nach unten kommt. Aber wie werde ich das tun. Hilf mir, danke. –

4

GestureDetector.SimpleOnGestureListener für die Ansicht und Verwendung Methode Add to fail verursachen würde onSingleTapConfirmed in diesem.

Diese Methode wird nur aufgerufen, wenn Android OS die Berührung auf dem betreffenden Gerät bestätigt hat und nicht doppelt tippen.

Sie können für Android-Beispiele google.

+0

ja ich versuchte dies..aber ich habe einige andere Probleme mit diesem Singletap oder Doubletap. trotzdem danke. –

+0

onSingleTapConfirmed wird nur aufgerufen, wenn der Tap einzeln ist. Keine Verwirrung hier. Siehe den Methodennamen selbst sagt es onSingleTapConfirmed. Ich weiß nicht, auf welche anderen Probleme Sie sich beziehen, ich denke, Sie haben die Rückgabewerte nicht richtig gehandhabt. Prüfen Sie! – Charan

+0

mein Problem ist nicht mit Gesten-Listener, sondern mit meiner App. Meine App enthält benutzerdefinierte Ansichten mit Multitouch-Pan und Zoom in Otouch, die nicht gut mit Gesten Listener geht. –

29

Einzel und Double Tap in android erkennt ich die folgenden Methoden verwenden:

class GestureTap extends GestureDetector.SimpleOnGestureListener { 
    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     Log.i("onDoubleTap :", "" + e.getAction()); 
     return true; 
    } 

    @Override 
    public boolean onSingleTapConfirmed(MotionEvent e) { 
     Log.i("onSingleTap :", "" + e.getAction()); 
     return true; 
    } 
} 

Verwenden Sie es in Konstruktor GestureDetector:

detector = new GestureDetector(this, new GestureTap()); 

Und den folgenden Code in OnTouch Hörern hinzufügen

@Override 
public boolean onTouchEvent(MotionEvent event) { 

    detector.onTouchEvent(event); 

    return true; 
} 
+0

+1 Sir Danke, dass Sie meinen Job und mein Leben gerettet haben. Sie sind ein Engel. Hier ist auch die Referenz für mehr unterstützte Geste, die Sie überschreiben können: https://developer.android.com/training/gestures/detector.html#detect. Sehen Sie sich den Abschnitt "Gestenerkennung" an. –

2

Es gibt einen viel einfacheren und direkten Weg. Verwenden Sie MotionEvent.ACTION_DOWN & & MotionEvent.ACTION_UP und stellen Sie den Unterschied zwischen Ereignissen fest.

Der vollständige Code kann hier gefunden werden.https://stackoverflow.com/a/15799372/3659481

setOnTouchListener(new OnTouchListener() { 
private static final int MAX_CLICK_DURATION = 200; 
private long startClickTime; 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: { 
      startClickTime = Calendar.getInstance().getTimeInMillis(); 
      break; 
     } 
     case MotionEvent.ACTION_UP: { 
      long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime; 
      if(clickDuration < MAX_CLICK_DURATION) { 
       //click event has occurred 
      } 
     } 
    } 
    return true; 
} 

}

7

die Antwort auf Vollständigkeit halber hinzufügen und wenn jemand anderes hier erreicht:

Sie eine GestureDetector mit einem OnTouchListener

final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { 
     @Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
     //do something 
      return true; 
     } 

     @Override 
     public void onLongPress(MotionEvent e) { 
      super.onLongPress(e); 
     } 

     @Override 
     public boolean onDoubleTap(MotionEvent e) { 
      return super.onDoubleTap(e); 
     } 
    }); 

viewToTouch.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      return gestureDetector.onTouchEvent(event); 
     } 
    }); 
0
float dX,dY,x,y;  
tv.setOnTouchListener(new View.OnTouchListener() { 
           @Override 
           public boolean onTouch(View view, MotionEvent event) { 
            switch (event.getAction()) { 
             case MotionEvent.ACTION_UP:  //Event for On Click 
              if(x==view.getX() && y==view.getY()){ 
               Toast.makeText(getApplicationContext(),"TextView Clicked",Toast.LENGTH_LONG).show(); 
              } 
              break; 
             case MotionEvent.ACTION_DOWN: 
              x=view.getX(); 
              y=view.getY(); 
              dX = view.getX() - event.getRawX(); 
              dY = view.getY() - event.getRawY(); 
              break; 

             case MotionEvent.ACTION_MOVE: 
              view.animate() 
                .x(event.getRawX() + dX) 
                .y(event.getRawY() + dY) 
                .setDuration(0) 
                .start(); 
              break; 
             default: 
              return false; 
            } 
            return true; 
           } 
          });